refactor!(core): Add context parameter to Middleware

This commit is contained in:
2026-04-12 18:27:07 +02:00
parent 615d3810a0
commit a413fab8d5
23 changed files with 234 additions and 110 deletions

View File

@@ -15,6 +15,8 @@ import de.siphalor.tweed5.serde.extension.api.TweedEntryReader;
import de.siphalor.tweed5.serde.extension.api.TweedEntryWriter; import de.siphalor.tweed5.serde.extension.api.TweedEntryWriter;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.extension.WriterMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult;
import de.siphalor.tweed5.serde.extension.impl.TweedEntryReaderWriterImpls; import de.siphalor.tweed5.serde.extension.impl.TweedEntryReaderWriterImpls;
import de.siphalor.tweed5.serde_api.api.DelegatingTweedDataWriter; import de.siphalor.tweed5.serde_api.api.DelegatingTweedDataWriter;
@@ -158,7 +160,7 @@ public class AttributesReadWriteFilterExtensionImpl
} }
} }
private class ReaderMiddleware implements Middleware<TweedEntryReader<?, ?>> { private class ReaderMiddleware implements Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -175,28 +177,28 @@ public class AttributesReadWriteFilterExtensionImpl
} }
@Override @Override
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) { public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner, ReaderMiddlewareContext context) {
assert readWriteContextDataAccess != null; assert readWriteContextDataAccess != null;
//noinspection unchecked //noinspection unchecked
TweedEntryReader<Object, ConfigEntry<Object>> innerCasted TweedEntryReader<Object, ConfigEntry<Object>> innerCasted
= (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner; = (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedEntryReader<Object, ConfigEntry<Object>>) (reader, entry, context) -> { return (TweedEntryReader<Object, ConfigEntry<Object>>) (reader, entry, readContext) -> {
ReadWriteContextCustomData contextData = context.extensionsData().get(readWriteContextDataAccess); ReadWriteContextCustomData contextData = readContext.extensionsData().get(readWriteContextDataAccess);
if (contextData == null) { if (contextData == null) {
contextData = new ReadWriteContextCustomData(); contextData = new ReadWriteContextCustomData();
context.extensionsData().set(readWriteContextDataAccess, contextData); readContext.extensionsData().set(readWriteContextDataAccess, contextData);
} }
if (!doFiltersMatch(entry, contextData)) { if (!doFiltersMatch(entry, contextData)) {
TweedEntryReaderWriterImpls.NOOP_READER_WRITER.read(reader, entry, context); TweedEntryReaderWriterImpls.NOOP_READER_WRITER.read(reader, entry, readContext);
return TweedReadResult.empty(); return TweedReadResult.empty();
} }
return innerCasted.read(reader, entry, context); return innerCasted.read(reader, entry, readContext);
}; };
} }
} }
private class WriterMiddleware implements Middleware<TweedEntryWriter<?, ?>> { private class WriterMiddleware implements Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext> {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -213,18 +215,18 @@ public class AttributesReadWriteFilterExtensionImpl
} }
@Override @Override
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) { public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner, WriterMiddlewareContext context) {
assert readWriteContextDataAccess != null; assert readWriteContextDataAccess != null;
//noinspection unchecked //noinspection unchecked
TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted
= (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner; = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedEntryWriter<@Nullable Object, @NonNull ConfigEntry<@Nullable Object>>) return (TweedEntryWriter<@Nullable Object, @NonNull ConfigEntry<@Nullable Object>>)
(writer, value, entry, context) -> { (writer, value, entry, writeContext) -> {
ReadWriteContextCustomData contextData = context.extensionsData() ReadWriteContextCustomData contextData = writeContext.extensionsData()
.get(readWriteContextDataAccess); .get(readWriteContextDataAccess);
if (contextData == null || contextData.attributeFilters().isEmpty()) { if (contextData == null || contextData.attributeFilters().isEmpty()) {
innerCasted.write(writer, value, entry, context); innerCasted.write(writer, value, entry, writeContext);
return; return;
} }
@@ -234,7 +236,7 @@ public class AttributesReadWriteFilterExtensionImpl
} }
if (doFiltersMatch(entry, contextData)) { if (doFiltersMatch(entry, contextData)) {
innerCasted.write(writer, value, entry, context); innerCasted.write(writer, value, entry, writeContext);
} else { } else {
try { try {
writer.visitValue(TWEED_DATA_NOTHING_VALUE); writer.visitValue(TWEED_DATA_NOTHING_VALUE);

View File

@@ -6,6 +6,7 @@ import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.container.ConfigContainerSetupPhase; import de.siphalor.tweed5.core.api.container.ConfigContainerSetupPhase;
import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext; import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducerMiddlewareContext;
import de.siphalor.tweed5.serde_api.api.IntuitiveVisitingTweedDataReader; import de.siphalor.tweed5.serde_api.api.IntuitiveVisitingTweedDataReader;
import de.siphalor.tweed5.serde_api.api.TweedDataReadException; import de.siphalor.tweed5.serde_api.api.TweedDataReadException;
import de.siphalor.tweed5.serde_api.api.TweedDataReader; import de.siphalor.tweed5.serde_api.api.TweedDataReader;
@@ -44,8 +45,8 @@ public class CommentLoaderExtensionImpl implements CommentLoaderExtension, Comme
} }
@Override @Override
public Middleware<CommentProducer> commentMiddleware() { public Middleware<CommentProducer, CommentProducerMiddlewareContext> commentMiddleware() {
return new Middleware<CommentProducer>() { return new Middleware<CommentProducer, CommentProducerMiddlewareContext>() {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -62,7 +63,10 @@ public class CommentLoaderExtensionImpl implements CommentLoaderExtension, Comme
} }
@Override @Override
public CommentProducer process(CommentProducer inner) { public CommentProducer process(CommentProducer inner, CommentProducerMiddlewareContext context) {
if (context.entry().extensionsData().get(loadedCommentAccess) == null) {
return inner;
}
return entry -> { return entry -> {
String loadedComment = entry.extensionsData().get(loadedCommentAccess); String loadedComment = entry.extensionsData().get(loadedCommentAccess);
String innerComment = inner.createComment(entry); String innerComment = inner.createComment(entry);

View File

@@ -8,11 +8,11 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> { public class DefaultMiddlewareContainer<M, C> implements MiddlewareContainer<M, C> {
private static final String CONTAINER_ID = ""; private static final String CONTAINER_ID = "";
@Getter @Getter
private List<Middleware<M>> middlewares = new ArrayList<>(); private List<Middleware<M, C>> middlewares = new ArrayList<>();
private final Set<String> middlewareIds = new HashSet<>(); private final Set<String> middlewareIds = new HashSet<>();
private boolean sealed = false; private boolean sealed = false;
@@ -22,10 +22,10 @@ public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> {
} }
@Override @Override
public void registerAll(Collection<Middleware<M>> middlewares) { public void registerAll(Collection<Middleware<M, C>> middlewares) {
requireUnsealed(); requireUnsealed();
for (Middleware<M> middleware : middlewares) { for (Middleware<M, C> middleware : middlewares) {
if (middleware.id().isEmpty()) { if (middleware.id().isEmpty()) {
throw new IllegalArgumentException("Middleware id cannot be empty"); throw new IllegalArgumentException("Middleware id cannot be empty");
} }
@@ -37,7 +37,7 @@ public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> {
} }
@Override @Override
public void register(Middleware<M> middleware) { public void register(Middleware<M, C> middleware) {
requireUnsealed(); requireUnsealed();
if (middleware.id().isEmpty()) { if (middleware.id().isEmpty()) {
@@ -76,7 +76,7 @@ public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> {
AcyclicGraphSorter sorter = new AcyclicGraphSorter(allMentionedMiddlewareIds.length); AcyclicGraphSorter sorter = new AcyclicGraphSorter(allMentionedMiddlewareIds.length);
for (Middleware<M> middleware : middlewares) { for (Middleware<M, C> middleware : middlewares) {
Integer currentIndex = indecesByMiddlewareId.get(middleware.id()); Integer currentIndex = indecesByMiddlewareId.get(middleware.id());
middleware.mustComeAfter().stream() middleware.mustComeAfter().stream()
@@ -87,7 +87,8 @@ public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> {
.forEach(afterIndex -> sorter.addEdge(currentIndex, afterIndex)); .forEach(afterIndex -> sorter.addEdge(currentIndex, afterIndex));
} }
Map<String, Middleware<M>> middlewaresById = middlewares.stream().collect(Collectors.toMap(Middleware::id, Function.identity())); Map<String, Middleware<M, C>> middlewaresById = middlewares.stream()
.collect(Collectors.toMap(Middleware::id, Function.identity()));
try { try {
int[] sortedIndeces = sorter.sort(); int[] sortedIndeces = sorter.sort();
@@ -107,13 +108,27 @@ public class DefaultMiddlewareContainer<M> implements MiddlewareContainer<M> {
} }
@Override @Override
public M process(M inner, C context) {
if (!sealed) {
throw new IllegalStateException("Middleware container has not been sealed");
}
M combined = inner;
for (int i = middlewares.size() - 1; i >= 0; i--) {
Middleware<M, C> middleware = middlewares.get(i);
combined = middleware.process(combined, context);
}
return combined;
}
@Override
@Deprecated
public M process(M inner) { public M process(M inner) {
if (!sealed) { if (!sealed) {
throw new IllegalStateException("Middleware container has not been sealed"); throw new IllegalStateException("Middleware container has not been sealed");
} }
M combined = inner; M combined = inner;
for (int i = middlewares.size() - 1; i >= 0; i--) { for (int i = middlewares.size() - 1; i >= 0; i--) {
Middleware<M> middleware = middlewares.get(i); Middleware<M, C> middleware = middlewares.get(i);
combined = middleware.process(combined); combined = middleware.process(combined);
} }
return combined; return combined;

View File

@@ -1,9 +1,11 @@
package de.siphalor.tweed5.core.api.middleware; package de.siphalor.tweed5.core.api.middleware;
import org.jetbrains.annotations.ApiStatus;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
public interface Middleware<M> { public interface Middleware<M, C> {
String DEFAULT_START = "$default.start"; String DEFAULT_START = "$default.start";
String DEFAULT_END = "$default.end"; String DEFAULT_END = "$default.end";
@@ -16,5 +18,13 @@ public interface Middleware<M> {
return Collections.singleton(DEFAULT_START); return Collections.singleton(DEFAULT_START);
} }
M process(M inner); default M process(M inner, C context) {
return process(inner);
}
@Deprecated
@ApiStatus.OverrideOnly
default M process(M inner) {
return inner;
}
} }

View File

@@ -2,11 +2,11 @@ package de.siphalor.tweed5.core.api.middleware;
import java.util.Collection; import java.util.Collection;
public interface MiddlewareContainer<M> extends Middleware<M> { public interface MiddlewareContainer<M, C> extends Middleware<M, C> {
default void registerAll(Collection<Middleware<M>> middlewares) { default void registerAll(Collection<Middleware<M, C>> middlewares) {
middlewares.forEach(this::register); middlewares.forEach(this::register);
} }
void register(Middleware<M> middleware); void register(Middleware<M, C> middleware);
void seal(); void seal();
Collection<Middleware<M>> middlewares(); Collection<Middleware<M, C>> middlewares();
} }

View File

@@ -3,5 +3,5 @@ package de.siphalor.tweed5.defaultextensions.comment.api;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
public interface CommentModifyingExtension { public interface CommentModifyingExtension {
Middleware<CommentProducer> commentMiddleware(); Middleware<CommentProducer, CommentProducerMiddlewareContext> commentMiddleware();
} }

View File

@@ -0,0 +1,14 @@
package de.siphalor.tweed5.defaultextensions.comment.api;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Value
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class CommentProducerMiddlewareContext {
ConfigEntry<?> entry;
}

View File

@@ -6,6 +6,7 @@ import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.extension.TweedExtension; import de.siphalor.tweed5.core.api.extension.TweedExtension;
import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext; import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext;
import de.siphalor.tweed5.core.api.middleware.DefaultMiddlewareContainer; import de.siphalor.tweed5.core.api.middleware.DefaultMiddlewareContainer;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducerMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentExtension; import de.siphalor.tweed5.defaultextensions.comment.api.CommentExtension;
@@ -20,7 +21,7 @@ public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentE
private final ConfigContainer<?> configContainer; private final ConfigContainer<?> configContainer;
@Getter @Getter
private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess; private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess;
private final DefaultMiddlewareContainer<CommentProducer> middlewareContainer; private final DefaultMiddlewareContainer<CommentProducer, CommentProducerMiddlewareContext> middlewareContainer;
@Getter @Getter
private @Nullable PatchworkPartAccess<Boolean> writerInstalledReadWriteContextAccess; private @Nullable PatchworkPartAccess<Boolean> writerInstalledReadWriteContextAccess;
@@ -71,7 +72,10 @@ public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentE
public void recomputeFullComments() { public void recomputeFullComments() {
configContainer.rootEntry().visitInOrder(entry -> { configContainer.rootEntry().visitInOrder(entry -> {
CustomEntryData entryData = getOrCreateCustomEntryData(entry); CustomEntryData entryData = getOrCreateCustomEntryData(entry);
entryData.commentProducer(middlewareContainer.process(_entry -> entryData.baseComment())); entryData.commentProducer(middlewareContainer.process(
_entry -> entryData.baseComment(),
CommentProducerMiddlewareContext.builder().entry(entry).build()
));
}); });
} }

View File

@@ -3,6 +3,7 @@ package de.siphalor.tweed5.defaultextensions.comment.impl;
import de.siphalor.tweed5.core.api.entry.ConfigEntry; import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.serde.extension.api.TweedEntryWriter; import de.siphalor.tweed5.serde.extension.api.TweedEntryWriter;
import de.siphalor.tweed5.serde.extension.api.extension.WriterMiddlewareContext;
import de.siphalor.tweed5.serde_api.api.DelegatingTweedDataWriter; import de.siphalor.tweed5.serde_api.api.DelegatingTweedDataWriter;
import de.siphalor.tweed5.serde_api.api.TweedDataVisitor; import de.siphalor.tweed5.serde_api.api.TweedDataVisitor;
import de.siphalor.tweed5.serde_api.api.decoration.TweedDataCommentDecoration; import de.siphalor.tweed5.serde_api.api.decoration.TweedDataCommentDecoration;
@@ -17,7 +18,7 @@ import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
@RequiredArgsConstructor @RequiredArgsConstructor
class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?, ?>> { class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext> {
private final CommentExtensionImpl commentExtension; private final CommentExtensionImpl commentExtension;
@Override @Override
@@ -26,15 +27,15 @@ class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?
} }
@Override @Override
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) { public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner, WriterMiddlewareContext context) {
PatchworkPartAccess<Boolean> writerInstalledAccess = commentExtension.writerInstalledReadWriteContextAccess(); PatchworkPartAccess<Boolean> writerInstalledAccess = commentExtension.writerInstalledReadWriteContextAccess();
assert writerInstalledAccess != null; assert writerInstalledAccess != null;
//noinspection unchecked //noinspection unchecked
TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner; TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) (writer, value, entry, context) -> { return (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) (writer, value, entry, writeContext) -> {
if (!Boolean.TRUE.equals(context.extensionsData().get(writerInstalledAccess))) { if (!Boolean.TRUE.equals(writeContext.extensionsData().get(writerInstalledAccess))) {
context.extensionsData().set(writerInstalledAccess, Boolean.TRUE); writeContext.extensionsData().set(writerInstalledAccess, Boolean.TRUE);
writer = new MapEntryKeyDeferringWriter(writer); writer = new MapEntryKeyDeferringWriter(writer);
} }
@@ -44,7 +45,7 @@ class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?
writer.visitDecoration(new PiercingCommentDecoration(() -> comment)); writer.visitDecoration(new PiercingCommentDecoration(() -> comment));
} }
innerCasted.write(writer, value, entry, context); innerCasted.write(writer, value, entry, writeContext);
}; };
} }

View File

@@ -6,6 +6,7 @@ import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.serde.extension.api.TweedEntryReader; import de.siphalor.tweed5.serde.extension.api.TweedEntryReader;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult;
import de.siphalor.tweed5.defaultextensions.patch.api.PatchExtension; import de.siphalor.tweed5.defaultextensions.patch.api.PatchExtension;
import de.siphalor.tweed5.defaultextensions.patch.api.PatchInfo; import de.siphalor.tweed5.defaultextensions.patch.api.PatchInfo;
@@ -81,22 +82,22 @@ public class PatchExtensionImpl implements PatchExtension, ReadWriteRelatedExten
} }
} }
private class ReaderMiddleware implements Middleware<TweedEntryReader<?, ?>> { private class ReaderMiddleware implements Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> {
@Override @Override
public String id() { public String id() {
return "patch-info-collector"; return "patch-info-collector";
} }
@Override @Override
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) { public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner, ReaderMiddlewareContext context) {
assert readWriteContextDataAccess != null; assert readWriteContextDataAccess != null;
//noinspection unchecked //noinspection unchecked
TweedEntryReader<Object, ConfigEntry<Object>> innerCasted = TweedEntryReader<Object, ConfigEntry<Object>> innerCasted =
(TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner; (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedEntryReader<Object, ConfigEntry<Object>>) (reader, entry, context) -> { return (TweedEntryReader<Object, ConfigEntry<Object>>) (reader, entry, readContext) -> {
TweedReadResult<Object> readResult = innerCasted.read(reader, entry, context); TweedReadResult<Object> readResult = innerCasted.read(reader, entry, readContext);
ReadWriteContextCustomData customData = context.extensionsData().get(readWriteContextDataAccess); ReadWriteContextCustomData customData = readContext.extensionsData().get(readWriteContextDataAccess);
if (customData != null && customData.patchInfo() != null) { if (customData != null && customData.patchInfo() != null) {
customData.patchInfo().addEntry(entry); customData.patchInfo().addEntry(entry);
} }

View File

@@ -5,6 +5,8 @@ import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.serde.extension.api.*; import de.siphalor.tweed5.serde.extension.api.*;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.extension.WriterMiddlewareContext;
import de.siphalor.tweed5.serde_api.api.TweedDataReader; import de.siphalor.tweed5.serde_api.api.TweedDataReader;
import de.siphalor.tweed5.serde_api.api.TweedDataVisitor; import de.siphalor.tweed5.serde_api.api.TweedDataVisitor;
import de.siphalor.tweed5.defaultextensions.pather.api.PathTracking; import de.siphalor.tweed5.defaultextensions.pather.api.PathTracking;
@@ -48,59 +50,59 @@ public class PatherExtensionImpl implements PatherExtension, ReadWriteRelatedExt
return pathTracking.currentPath(); return pathTracking.currentPath();
} }
private Middleware<TweedEntryReader<?, ?>> createEntryReaderMiddleware() { private Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> createEntryReaderMiddleware() {
return new Middleware<TweedEntryReader<?, ?>>() { return new Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext>() {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
} }
@Override @Override
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) { public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner, ReaderMiddlewareContext context) {
assert rwContextPathTrackingAccess != null; assert rwContextPathTrackingAccess != null;
//noinspection unchecked //noinspection unchecked
val castedInner = (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner; val castedInner = (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) -> { return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext readContext) -> {
PathTracking pathTracking = context.extensionsData().get(rwContextPathTrackingAccess); PathTracking pathTracking = readContext.extensionsData().get(rwContextPathTrackingAccess);
if (pathTracking != null) { if (pathTracking != null) {
return castedInner.read(reader, entry, context); return castedInner.read(reader, entry, readContext);
} }
pathTracking = PathTracking.create(); pathTracking = PathTracking.create();
context.extensionsData().set(rwContextPathTrackingAccess, pathTracking); readContext.extensionsData().set(rwContextPathTrackingAccess, pathTracking);
return castedInner.read(new PathTrackingDataReader(reader, pathTracking), entry, context); return castedInner.read(new PathTrackingDataReader(reader, pathTracking), entry, readContext);
}; };
} }
}; };
} }
private Middleware<TweedEntryWriter<?, ?>> createEntryWriterMiddleware() { private Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext> createEntryWriterMiddleware() {
return new Middleware<TweedEntryWriter<?, ?>>() { return new Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext>() {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
} }
@Override @Override
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) { public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner, WriterMiddlewareContext context) {
assert rwContextPathTrackingAccess != null; assert rwContextPathTrackingAccess != null;
//noinspection unchecked //noinspection unchecked
val castedInner = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner; val castedInner = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedDataVisitor writer, Object value, ConfigEntry<Object> entry, TweedWriteContext context) -> { return (TweedDataVisitor writer, Object value, ConfigEntry<Object> entry, TweedWriteContext writeContext) -> {
PathTracking pathTracking = context.extensionsData().get(rwContextPathTrackingAccess); PathTracking pathTracking = writeContext.extensionsData().get(rwContextPathTrackingAccess);
if (pathTracking != null) { if (pathTracking != null) {
castedInner.write(writer, value, entry, context); castedInner.write(writer, value, entry, writeContext);
return; return;
} }
pathTracking = PathTracking.create(); pathTracking = PathTracking.create();
context.extensionsData().set(rwContextPathTrackingAccess, pathTracking); writeContext.extensionsData().set(rwContextPathTrackingAccess, pathTracking);
try { try {
castedInner.write(new PathTrackingDataVisitor(writer, pathTracking), value, entry, context); castedInner.write(new PathTrackingDataVisitor(writer, pathTracking), value, entry, writeContext);
} catch (TweedEntryWriteException e) { } catch (TweedEntryWriteException e) {
PathTracking exceptionPathTracking = PathTracking exceptionPathTracking =
e.context().extensionsData().get(rwContextPathTrackingAccess); e.context().extensionsData().get(rwContextPathTrackingAccess);

View File

@@ -10,6 +10,7 @@ import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension; import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension;
import de.siphalor.tweed5.defaultextensions.readfallback.api.ReadFallbackExtension; import de.siphalor.tweed5.defaultextensions.readfallback.api.ReadFallbackExtension;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension; import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult;
import lombok.extern.apachecommons.CommonsLog; import lombok.extern.apachecommons.CommonsLog;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
@@ -30,7 +31,7 @@ public class ReadFallbackExtensionImpl implements ReadFallbackExtension, ReadWri
PresetsExtension presetsExtension = configContainer.extension(PresetsExtension.class) PresetsExtension presetsExtension = configContainer.extension(PresetsExtension.class)
.orElseThrow(() -> new IllegalStateException(getClass().getSimpleName() .orElseThrow(() -> new IllegalStateException(getClass().getSimpleName()
+ " requires " + ReadFallbackExtension.class.getSimpleName())); + " requires " + ReadFallbackExtension.class.getSimpleName()));
context.registerReaderMiddleware(new Middleware<TweedEntryReader<?, ?>>() { context.registerReaderMiddleware(new Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext>() {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -47,18 +48,18 @@ public class ReadFallbackExtensionImpl implements ReadFallbackExtension, ReadWri
} }
@Override @Override
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) { public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner, ReaderMiddlewareContext context) {
//noinspection unchecked //noinspection unchecked
TweedEntryReader<Object, ConfigEntry<Object>> castedInner = TweedEntryReader<Object, ConfigEntry<Object>> castedInner =
(TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner; (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) inner;
return (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) (reader, entry, context) -> return (TweedEntryReader<Object, @NonNull ConfigEntry<Object>>) (reader, entry, readContext) ->
castedInner.read(reader, entry, context).catchError( castedInner.read(reader, entry, readContext).catchError(
issues -> { issues -> {
Object fallback = Object fallback =
presetsExtension.presetValue(entry, PresetsExtension.DEFAULT_PRESET_NAME); presetsExtension.presetValue(entry, PresetsExtension.DEFAULT_PRESET_NAME);
return TweedReadResult.withIssues(fallback, issues); return TweedReadResult.withIssues(fallback, issues);
}, },
context readContext
); );
} }
}); });

View File

@@ -8,6 +8,7 @@ import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResu
import de.siphalor.tweed5.defaultextensions.validation.api.validators.SimpleValidatorMiddleware; import de.siphalor.tweed5.defaultextensions.validation.api.validators.SimpleValidatorMiddleware;
import de.siphalor.tweed5.defaultextensions.validation.impl.ValidationExtensionImpl; import de.siphalor.tweed5.defaultextensions.validation.impl.ValidationExtensionImpl;
import de.siphalor.tweed5.patchwork.api.Patchwork; import de.siphalor.tweed5.patchwork.api.Patchwork;
import org.jetbrains.annotations.UnknownNullability;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import java.util.*; import java.util.*;
@@ -55,7 +56,10 @@ public interface ValidationExtension extends TweedExtension {
lastId = id; lastId = id;
} }
} }
<T> void addValidatorMiddleware(ConfigEntry<T> entry, Middleware<ConfigEntryValidator> validator); <T> void addValidatorMiddleware(
ConfigEntry<T> entry,
Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> validator
);
ValidationIssues captureValidationIssues(Patchwork readContextExtensionsData); ValidationIssues captureValidationIssues(Patchwork readContextExtensionsData);

View File

@@ -3,5 +3,5 @@ package de.siphalor.tweed5.defaultextensions.validation.api;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
public interface ValidationProvidingExtension { public interface ValidationProvidingExtension {
Middleware<ConfigEntryValidator> validationMiddleware(); Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> validationMiddleware();
} }

View File

@@ -0,0 +1,13 @@
package de.siphalor.tweed5.defaultextensions.validation.api;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Value
@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@Builder
public class ValidatorMiddlewareContext {
ConfigEntry<?> entry;
}

View File

@@ -3,6 +3,7 @@ package de.siphalor.tweed5.defaultextensions.validation.api.validators;
import de.siphalor.tweed5.core.api.entry.ConfigEntry; import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator; import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidatorMiddlewareContext;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -10,12 +11,12 @@ import org.jspecify.annotations.Nullable;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class SimpleValidatorMiddleware implements Middleware<ConfigEntryValidator> { public class SimpleValidatorMiddleware implements Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> {
String id; String id;
ConfigEntryValidator validator; ConfigEntryValidator validator;
@Override @Override
public ConfigEntryValidator process(ConfigEntryValidator inner) { public ConfigEntryValidator process(ConfigEntryValidator inner, ValidatorMiddlewareContext context) {
return new ConfigEntryValidator() { return new ConfigEntryValidator() {
@Override @Override
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) { public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {

View File

@@ -11,6 +11,7 @@ import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.core.api.middleware.MiddlewareContainer; import de.siphalor.tweed5.core.api.middleware.MiddlewareContainer;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentModifyingExtension; import de.siphalor.tweed5.defaultextensions.comment.api.CommentModifyingExtension;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducer; import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducer;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducerMiddlewareContext;
import de.siphalor.tweed5.defaultextensions.pather.api.PathTracking; import de.siphalor.tweed5.defaultextensions.pather.api.PathTracking;
import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingConfigEntryValueVisitor; import de.siphalor.tweed5.defaultextensions.pather.api.PathTrackingConfigEntryValueVisitor;
import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension; import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
@@ -18,6 +19,7 @@ import de.siphalor.tweed5.defaultextensions.pather.api.ValuePathTracking;
import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator; import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension; import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationProvidingExtension; import de.siphalor.tweed5.defaultextensions.validation.api.ValidationProvidingExtension;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidatorMiddlewareContext;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues;
@@ -28,10 +30,12 @@ import de.siphalor.tweed5.serde.extension.api.TweedEntryReader;
import de.siphalor.tweed5.serde.extension.api.TweedReadContext; import de.siphalor.tweed5.serde.extension.api.TweedReadContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadIssue; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadIssue;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult;
import de.siphalor.tweed5.serde_api.api.TweedDataReader; import de.siphalor.tweed5.serde_api.api.TweedDataReader;
import lombok.*; import lombok.*;
import org.jetbrains.annotations.UnknownNullability;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import java.util.*; import java.util.*;
@@ -70,8 +74,8 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
private final ConfigContainer<?> configContainer; private final ConfigContainer<?> configContainer;
private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess; private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess;
private final MiddlewareContainer<ConfigEntryValidator> entryValidatorMiddlewareContainer private final MiddlewareContainer<ConfigEntryValidator, ValidatorMiddlewareContext>
= new DefaultMiddlewareContainer<>(); entryValidatorMiddlewareContainer = new DefaultMiddlewareContainer<>();
private @Nullable PatchworkPartAccess<ValidationIssues> readContextValidationIssuesAccess; private @Nullable PatchworkPartAccess<ValidationIssues> readContextValidationIssuesAccess;
private @Nullable PatherExtension patherExtension; private @Nullable PatherExtension patherExtension;
@@ -97,15 +101,15 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
} }
@Override @Override
public Middleware<CommentProducer> commentMiddleware() { public Middleware<CommentProducer, CommentProducerMiddlewareContext> commentMiddleware() {
return new Middleware<CommentProducer>() { return new Middleware<CommentProducer, CommentProducerMiddlewareContext>() {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
} }
@Override @Override
public CommentProducer process(CommentProducer inner) { public CommentProducer process(CommentProducer inner, CommentProducerMiddlewareContext context) {
return entry -> { return entry -> {
String baseComment = inner.createComment(entry); String baseComment = inner.createComment(entry);
CustomEntryData entryData = entry.extensionsData().get(customEntryDataAccess); CustomEntryData entryData = entry.extensionsData().get(customEntryDataAccess);
@@ -135,7 +139,10 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
} }
@Override @Override
public <T> void addValidatorMiddleware(ConfigEntry<T> entry, Middleware<ConfigEntryValidator> validator) { public <T> void addValidatorMiddleware(
ConfigEntry<T> entry,
Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> validator
) {
CustomEntryData entryData = getOrCreateCustomEntryData(entry); CustomEntryData entryData = getOrCreateCustomEntryData(entry);
entryData.addValidator(validator); entryData.addValidator(validator);
} }
@@ -152,13 +159,20 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
CustomEntryData entryData = getOrCreateCustomEntryData(configEntry); CustomEntryData entryData = getOrCreateCustomEntryData(configEntry);
if (entryData.validators().isEmpty()) { if (entryData.validators().isEmpty()) {
entryData.completeValidator(entryValidatorMiddlewareContainer.process(baseValidator)); entryData.completeValidator(entryValidatorMiddlewareContainer.process(
baseValidator,
ValidatorMiddlewareContext.builder().entry(configEntry).build()
));
} else { } else {
DefaultMiddlewareContainer<ConfigEntryValidator> entrySpecificValidatorContainer = new DefaultMiddlewareContainer<>(); DefaultMiddlewareContainer<ConfigEntryValidator, ValidatorMiddlewareContext> entrySpecificValidatorContainer
= new DefaultMiddlewareContainer<>();
entrySpecificValidatorContainer.registerAll(entryValidatorMiddlewareContainer.middlewares()); entrySpecificValidatorContainer.registerAll(entryValidatorMiddlewareContainer.middlewares());
entrySpecificValidatorContainer.registerAll(entryData.validators()); entrySpecificValidatorContainer.registerAll(entryData.validators());
entrySpecificValidatorContainer.seal(); entrySpecificValidatorContainer.seal();
entryData.completeValidator(entrySpecificValidatorContainer.process(baseValidator)); entryData.completeValidator(entrySpecificValidatorContainer.process(
baseValidator,
ValidatorMiddlewareContext.builder().entry(configEntry).build()
));
} }
} }
@@ -199,14 +213,14 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
@Data @Data
private static class CustomEntryData { private static class CustomEntryData {
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private @Nullable List<Middleware<ConfigEntryValidator>> validators; private @Nullable List<Middleware<ConfigEntryValidator, ValidatorMiddlewareContext>> validators;
private @Nullable ConfigEntryValidator completeValidator; private @Nullable ConfigEntryValidator completeValidator;
public List<Middleware<ConfigEntryValidator>> validators() { public List<Middleware<ConfigEntryValidator, ValidatorMiddlewareContext>> validators() {
return validators == null ? Collections.emptyList() : validators; return validators == null ? Collections.emptyList() : validators;
} }
public void addValidator(Middleware<ConfigEntryValidator> validator) { public void addValidator(Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> validator) {
if (validators == null) { if (validators == null) {
validators = new ArrayList<>(); validators = new ArrayList<>();
} }
@@ -214,7 +228,8 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
} }
} }
private class EntryValidationReaderMiddleware implements Middleware<TweedEntryReader<?, ?>> { private class EntryValidationReaderMiddleware
implements Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -226,15 +241,15 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
} }
@Override @Override
public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner) { public TweedEntryReader<?, ?> process(TweedEntryReader<?, ?> inner, ReaderMiddlewareContext context) {
assert readContextValidationIssuesAccess != null && patherExtension != null; assert readContextValidationIssuesAccess != null && patherExtension != null;
//noinspection unchecked //noinspection unchecked
TweedEntryReader<Object, ConfigEntry<Object>> castedInner = (TweedEntryReader<Object, ConfigEntry<Object>>) inner; TweedEntryReader<Object, ConfigEntry<Object>> castedInner = (TweedEntryReader<Object, ConfigEntry<Object>>) inner;
return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext context) -> { return (TweedDataReader reader, ConfigEntry<Object> entry, TweedReadContext readContext) -> {
ValidationIssues validationIssues = getOrCreateValidationIssues(context.extensionsData()); ValidationIssues validationIssues = getOrCreateValidationIssues(readContext.extensionsData());
return castedInner.read(reader, entry, context).andThen(value -> { return castedInner.read(reader, entry, readContext).andThen(value -> {
ConfigEntryValidator entryValidator = entry.extensionsData() ConfigEntryValidator entryValidator = entry.extensionsData()
.get(customEntryDataAccess) .get(customEntryDataAccess)
.completeValidator(); .completeValidator();
@@ -246,22 +261,22 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
return TweedReadResult.ok(validationResult.value()); return TweedReadResult.ok(validationResult.value());
} }
String path = patherExtension.getPath(context); String path = patherExtension.getPath(readContext);
validationIssues.issuesByPath().put(path, new ValidationIssues.EntryIssues( validationIssues.issuesByPath().put(path, new ValidationIssues.EntryIssues(
entry, entry,
validationResult.issues() validationResult.issues()
)); ));
if (validationResult.hasError()) { if (validationResult.hasError()) {
return TweedReadResult.failed( return TweedReadResult.failed(
mapValidationIssuesToReadIssues(validationResult.issues(), context) mapValidationIssuesToReadIssues(validationResult.issues(), readContext)
); );
} else { } else {
return TweedReadResult.withIssues( return TweedReadResult.withIssues(
validationResult.value(), validationResult.value(),
mapValidationIssuesToReadIssues(validationResult.issues(), context) mapValidationIssuesToReadIssues(validationResult.issues(), readContext)
); );
} }
}, context); }, readContext);
}; };
} }
} }

View File

@@ -7,6 +7,7 @@ import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension; import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension;
import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator; import de.siphalor.tweed5.defaultextensions.validation.api.ConfigEntryValidator;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationProvidingExtension; import de.siphalor.tweed5.defaultextensions.validation.api.ValidationProvidingExtension;
import de.siphalor.tweed5.defaultextensions.validation.api.ValidatorMiddlewareContext;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssue;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssueLevel;
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult; import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationResult;
@@ -62,11 +63,11 @@ public class ValidationFallbackExtensionImpl implements ValidationFallbackExtens
} }
@Override @Override
public Middleware<ConfigEntryValidator> validationMiddleware() { public Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> validationMiddleware() {
return new ValidationFallbackMiddleware(); return new ValidationFallbackMiddleware();
} }
private class ValidationFallbackMiddleware implements Middleware<ConfigEntryValidator> { private class ValidationFallbackMiddleware implements Middleware<ConfigEntryValidator, ValidatorMiddlewareContext> {
@Override @Override
public String id() { public String id() {
return EXTENSION_ID; return EXTENSION_ID;
@@ -83,7 +84,7 @@ public class ValidationFallbackExtensionImpl implements ValidationFallbackExtens
} }
@Override @Override
public ConfigEntryValidator process(ConfigEntryValidator inner) { public ConfigEntryValidator process(ConfigEntryValidator inner, ValidatorMiddlewareContext context) {
return new ConfigEntryValidator() { return new ConfigEntryValidator() {
@Override @Override
public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) { public <T extends @Nullable Object> ValidationResult<T> validate(ConfigEntry<T> configEntry, T value) {

View File

@@ -9,6 +9,7 @@ import de.siphalor.tweed5.core.impl.DefaultConfigContainer;
import de.siphalor.tweed5.core.impl.entry.NullableConfigEntryImpl; import de.siphalor.tweed5.core.impl.entry.NullableConfigEntryImpl;
import de.siphalor.tweed5.core.impl.entry.SimpleConfigEntryImpl; import de.siphalor.tweed5.core.impl.entry.SimpleConfigEntryImpl;
import de.siphalor.tweed5.core.impl.entry.StaticMapCompoundConfigEntryImpl; import de.siphalor.tweed5.core.impl.entry.StaticMapCompoundConfigEntryImpl;
import de.siphalor.tweed5.defaultextensions.comment.api.CommentProducerMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.ReadWriteExtension; import de.siphalor.tweed5.serde.extension.api.ReadWriteExtension;
import de.siphalor.tweed5.serde.hjson.HjsonCommentType; import de.siphalor.tweed5.serde.hjson.HjsonCommentType;
import de.siphalor.tweed5.serde.hjson.HjsonWriter; import de.siphalor.tweed5.serde.hjson.HjsonWriter;
@@ -144,7 +145,7 @@ class CommentExtensionImplTest {
} }
@Override @Override
public Middleware<CommentProducer> commentMiddleware() { public Middleware<CommentProducer, CommentProducerMiddlewareContext> commentMiddleware() {
return new Middleware<>() { return new Middleware<>() {
@Override @Override
public String id() { public String id() {
@@ -152,7 +153,7 @@ class CommentExtensionImplTest {
} }
@Override @Override
public CommentProducer process(CommentProducer inner) { public CommentProducer process(CommentProducer inner, CommentProducerMiddlewareContext context) {
return entry -> "The comment is:\n" + inner.createComment(entry) + "\nEND"; return entry -> "The comment is:\n" + inner.createComment(entry) + "\nEND";
} }
}; };

View File

@@ -7,6 +7,6 @@ import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
public interface ReadWriteExtensionSetupContext { public interface ReadWriteExtensionSetupContext {
<E> PatchworkPartAccess<E> registerReadWriteContextExtensionData(Class<E> extensionDataClass); <E> PatchworkPartAccess<E> registerReadWriteContextExtensionData(Class<E> extensionDataClass);
void registerReaderMiddleware(Middleware<TweedEntryReader<?, ?>> middleware); void registerReaderMiddleware(Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> middleware);
void registerWriterMiddleware(Middleware<TweedEntryWriter<?, ?>> middleware); void registerWriterMiddleware(Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext> middleware);
} }

View File

@@ -0,0 +1,11 @@
package de.siphalor.tweed5.serde.extension.api.extension;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import lombok.*;
@Value
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class ReaderMiddlewareContext {
ConfigEntry<?> entry;
}

View File

@@ -0,0 +1,14 @@
package de.siphalor.tweed5.serde.extension.api.extension;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
@Value
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class WriterMiddlewareContext {
ConfigEntry<?> entry;
}

View File

@@ -6,16 +6,18 @@ import de.siphalor.tweed5.core.api.extension.TweedExtension;
import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext; import de.siphalor.tweed5.core.api.extension.TweedExtensionSetupContext;
import de.siphalor.tweed5.core.api.middleware.DefaultMiddlewareContainer; import de.siphalor.tweed5.core.api.middleware.DefaultMiddlewareContainer;
import de.siphalor.tweed5.core.api.middleware.Middleware; import de.siphalor.tweed5.core.api.middleware.Middleware;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import de.siphalor.tweed5.patchwork.api.PatchworkFactory;
import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
import de.siphalor.tweed5.serde.extension.api.*; import de.siphalor.tweed5.serde.extension.api.*;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteExtensionSetupContext;
import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension; import de.siphalor.tweed5.serde.extension.api.extension.ReadWriteRelatedExtension;
import de.siphalor.tweed5.serde.extension.api.extension.ReaderMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.extension.WriterMiddlewareContext;
import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult; import de.siphalor.tweed5.serde.extension.api.read.result.TweedReadResult;
import de.siphalor.tweed5.serde_api.api.TweedDataReader; import de.siphalor.tweed5.serde_api.api.TweedDataReader;
import de.siphalor.tweed5.serde_api.api.TweedDataVisitor; import de.siphalor.tweed5.serde_api.api.TweedDataVisitor;
import de.siphalor.tweed5.serde_api.api.TweedDataWriteException; import de.siphalor.tweed5.serde_api.api.TweedDataWriteException;
import de.siphalor.tweed5.patchwork.api.Patchwork;
import de.siphalor.tweed5.patchwork.api.PatchworkFactory;
import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
import lombok.Data; import lombok.Data;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
@@ -24,12 +26,10 @@ import java.util.Collection;
public class ReadWriteExtensionImpl implements ReadWriteExtension { public class ReadWriteExtensionImpl implements ReadWriteExtension {
private final ConfigContainer<?> configContainer; private final ConfigContainer<?> configContainer;
private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess; private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess;
private DefaultMiddlewareContainer<TweedEntryReader<?, ?>> private DefaultMiddlewareContainer<TweedEntryReader<?, ?>, ReaderMiddlewareContext>
entryReaderMiddlewareContainer entryReaderMiddlewareContainer = new DefaultMiddlewareContainer<>();
= new DefaultMiddlewareContainer<>(); private DefaultMiddlewareContainer<TweedEntryWriter<?, ?>, WriterMiddlewareContext>
private DefaultMiddlewareContainer<TweedEntryWriter<?, ?>> entryWriterMiddlewareContainer = new DefaultMiddlewareContainer<>();
entryWriterMiddlewareContainer
= new DefaultMiddlewareContainer<>();
private @Nullable PatchworkFactory readWriteContextPatchworkFactory; private @Nullable PatchworkFactory readWriteContextPatchworkFactory;
public ReadWriteExtensionImpl(ConfigContainer<?> configContainer, TweedExtensionSetupContext context) { public ReadWriteExtensionImpl(ConfigContainer<?> configContainer, TweedExtensionSetupContext context) {
@@ -52,12 +52,16 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
} }
@Override @Override
public void registerReaderMiddleware(Middleware<TweedEntryReader<?, ?>> middleware) { public void registerReaderMiddleware(
Middleware<TweedEntryReader<?, ?>, ReaderMiddlewareContext> middleware
) {
entryReaderMiddlewareContainer.register(middleware); entryReaderMiddlewareContainer.register(middleware);
} }
@Override @Override
public void registerWriterMiddleware(Middleware<TweedEntryWriter<?, ?>> middleware) { public void registerWriterMiddleware(
Middleware<TweedEntryWriter<?, ?>, WriterMiddlewareContext> middleware
) {
entryWriterMiddlewareContainer.register(middleware); entryWriterMiddlewareContainer.register(middleware);
} }
}; };
@@ -118,8 +122,14 @@ public class ReadWriteExtensionImpl implements ReadWriteExtension {
@Override @Override
public void initEntry(ConfigEntry<?> configEntry) { public void initEntry(ConfigEntry<?> configEntry) {
CustomEntryData customEntryData = getOrCreateCustomEntryData(configEntry); CustomEntryData customEntryData = getOrCreateCustomEntryData(configEntry);
customEntryData.readerChain(entryReaderMiddlewareContainer.process(customEntryData.readerDefinition())); customEntryData.readerChain(entryReaderMiddlewareContainer.process(
customEntryData.writerChain(entryWriterMiddlewareContainer.process(customEntryData.writerDefinition())); customEntryData.readerDefinition(),
ReaderMiddlewareContext.builder().entry(configEntry).build()
));
customEntryData.writerChain(entryWriterMiddlewareContainer.process(
customEntryData.writerDefinition(),
WriterMiddlewareContext.builder().entry(configEntry).build()
));
} }
private CustomEntryData getOrCreateCustomEntryData(ConfigEntry<?> entry) { private CustomEntryData getOrCreateCustomEntryData(ConfigEntry<?> entry) {