[serde-*, read-write-*] Support for visiting arbitrary decorations and values
This commit is contained in:
@@ -7,8 +7,7 @@ import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
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.core.api.middleware.Middleware;
|
||||
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
||||
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteExtensionSetupContext;
|
||||
import de.siphalor.tweed5.data.extension.api.extension.ReadWriteRelatedExtension;
|
||||
import de.siphalor.tweed5.defaultextensions.comment.api.CommentExtension;
|
||||
import de.siphalor.tweed5.defaultextensions.comment.api.CommentModifyingExtension;
|
||||
@@ -24,6 +23,8 @@ public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentE
|
||||
@Getter
|
||||
private final PatchworkPartAccess<CustomEntryData> customEntryDataAccess;
|
||||
private final DefaultMiddlewareContainer<CommentProducer> middlewareContainer;
|
||||
@Getter
|
||||
private @Nullable PatchworkPartAccess<Boolean> writerInstalledReadWriteContextAccess;
|
||||
|
||||
public CommentExtensionImpl(ConfigContainer<?> configContainer, TweedExtensionSetupContext context) {
|
||||
this.configContainer = configContainer;
|
||||
@@ -47,8 +48,9 @@ public class CommentExtensionImpl implements ReadWriteRelatedExtension, CommentE
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Middleware<TweedEntryWriter<?, ?>> entryWriterMiddleware() {
|
||||
return new TweedEntryWriterCommentMiddleware(this);
|
||||
public void setupReadWriteExtension(ReadWriteExtensionSetupContext context) {
|
||||
writerInstalledReadWriteContextAccess = context.registerReadWriteContextExtensionData(Boolean.class);
|
||||
context.registerWriterMiddleware(new TweedEntryWriterCommentMiddleware(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package de.siphalor.tweed5.defaultextensions.comment.impl;
|
||||
|
||||
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.middleware.Middleware;
|
||||
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
||||
import de.siphalor.tweed5.dataapi.api.DelegatingTweedDataVisitor;
|
||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||
import de.siphalor.tweed5.defaultextensions.comment.api.CommentExtension;
|
||||
import de.siphalor.tweed5.dataapi.api.decoration.TweedDataCommentDecoration;
|
||||
import de.siphalor.tweed5.dataapi.api.decoration.TweedDataDecoration;
|
||||
import de.siphalor.tweed5.patchwork.api.PatchworkPartAccess;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?, ?>> {
|
||||
private final CommentExtension commentExtension;
|
||||
private final CommentExtensionImpl commentExtension;
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
@@ -21,122 +27,73 @@ class TweedEntryWriterCommentMiddleware implements Middleware<TweedEntryWriter<?
|
||||
|
||||
@Override
|
||||
public TweedEntryWriter<?, ?> process(TweedEntryWriter<?, ?> inner) {
|
||||
PatchworkPartAccess<Boolean> writerInstalledAccess = commentExtension.writerInstalledReadWriteContextAccess();
|
||||
assert writerInstalledAccess != null;
|
||||
|
||||
//noinspection unchecked
|
||||
TweedEntryWriter<Object, ConfigEntry<Object>> innerCasted = (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) inner;
|
||||
return (TweedEntryWriter<Object, @NonNull ConfigEntry<Object>>) (writer, value, entry, context) -> {
|
||||
if (writer instanceof CompoundDataVisitor) {
|
||||
// Comment is already written in front of the key by the CompoundDataWriter,
|
||||
// so we don't have to write it here.
|
||||
// We also want to unwrap the original writer,
|
||||
// so that the special comment writing is limited to compounds.
|
||||
writer = ((CompoundDataVisitor) writer).delegate;
|
||||
} else {
|
||||
String comment = getEntryComment(entry);
|
||||
if (comment != null) {
|
||||
writer.visitComment(comment);
|
||||
}
|
||||
if (!Boolean.TRUE.equals(context.extensionsData().get(writerInstalledAccess))) {
|
||||
context.extensionsData().set(writerInstalledAccess, Boolean.TRUE);
|
||||
|
||||
writer = new MapEntryKeyDeferringWriter(writer);
|
||||
}
|
||||
|
||||
if (entry instanceof CompoundConfigEntry) {
|
||||
innerCasted.write(
|
||||
new CompoundDataVisitor(writer, ((CompoundConfigEntry<?>) entry)),
|
||||
value,
|
||||
entry,
|
||||
context
|
||||
);
|
||||
} else {
|
||||
innerCasted.write(writer, value, entry, context);
|
||||
String comment = commentExtension.getFullComment(entry);
|
||||
if (comment != null) {
|
||||
writer.visitDecoration(new PiercingCommentDecoration(() -> comment));
|
||||
}
|
||||
|
||||
innerCasted.write(writer, value, entry, context);
|
||||
};
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class CompoundDataVisitor implements TweedDataVisitor {
|
||||
private final TweedDataVisitor delegate;
|
||||
private final CompoundConfigEntry<?> compoundConfigEntry;
|
||||
private static class MapEntryKeyDeferringWriter extends DelegatingTweedDataVisitor {
|
||||
private final Deque<TweedDataDecoration> decorationQueue = new ArrayDeque<>();
|
||||
private @Nullable String mapEntryKey;
|
||||
|
||||
@Override
|
||||
public void visitNull() {
|
||||
delegate.visitNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBoolean(boolean value) {
|
||||
delegate.visitBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitByte(byte value) {
|
||||
delegate.visitByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitShort(short value) {
|
||||
delegate.visitShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInt(int value) {
|
||||
delegate.visitInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLong(long value) {
|
||||
delegate.visitLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFloat(float value) {
|
||||
delegate.visitFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDouble(double value) {
|
||||
delegate.visitDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitString(String value) {
|
||||
delegate.visitString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitListStart() {
|
||||
delegate.visitListStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitListEnd() {
|
||||
delegate.visitListEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMapStart() {
|
||||
delegate.visitMapStart();
|
||||
protected MapEntryKeyDeferringWriter(TweedDataVisitor delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMapEntryKey(String key) {
|
||||
ConfigEntry<?> subEntry = compoundConfigEntry.subEntries().get(key);
|
||||
String subEntryComment = getEntryComment(subEntry);
|
||||
if (subEntryComment != null) {
|
||||
delegate.visitComment(subEntryComment);
|
||||
if (mapEntryKey != null) {
|
||||
throw new IllegalStateException("Map entry key already visited");
|
||||
} else {
|
||||
mapEntryKey = key;
|
||||
}
|
||||
delegate.visitMapEntryKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMapEnd() {
|
||||
delegate.visitMapEnd();
|
||||
public void visitDecoration(TweedDataDecoration decoration) {
|
||||
if (decoration instanceof PiercingCommentDecoration) {
|
||||
super.visitDecoration(((PiercingCommentDecoration) decoration).commentDecoration());
|
||||
return;
|
||||
}
|
||||
if (mapEntryKey != null) {
|
||||
decorationQueue.addLast(decoration);
|
||||
} else {
|
||||
super.visitDecoration(decoration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitComment(String comment) {
|
||||
delegate.visitComment(comment);
|
||||
protected void beforeValueWrite() {
|
||||
if (mapEntryKey != null) {
|
||||
super.visitMapEntryKey(mapEntryKey);
|
||||
mapEntryKey = null;
|
||||
TweedDataDecoration decoration;
|
||||
while ((decoration = decorationQueue.pollFirst()) != null) {
|
||||
super.visitDecoration(decoration);
|
||||
}
|
||||
}
|
||||
super.beforeValueWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String getEntryComment(ConfigEntry<?> entry) {
|
||||
return commentExtension.getFullComment(entry);
|
||||
@Value
|
||||
private static class PiercingCommentDecoration implements TweedDataDecoration {
|
||||
TweedDataCommentDecoration commentDecoration;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package de.siphalor.tweed5.defaultextensions.pather.api;
|
||||
|
||||
import de.siphalor.tweed5.dataapi.api.TweedDataUnsupportedValueException;
|
||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||
import de.siphalor.tweed5.dataapi.api.decoration.TweedDataDecoration;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PathTrackingDataVisitor implements TweedDataVisitor {
|
||||
@@ -62,6 +65,12 @@ public class PathTrackingDataVisitor implements TweedDataVisitor {
|
||||
valueVisited();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitValue(@Nullable Object value) throws TweedDataUnsupportedValueException {
|
||||
TweedDataVisitor.super.visitValue(value);
|
||||
valueVisited();
|
||||
}
|
||||
|
||||
private void valueVisited() {
|
||||
if (pathTracking.currentContext() == PathTracking.Context.LIST) {
|
||||
pathTracking.incrementListIndex();
|
||||
@@ -103,7 +112,7 @@ public class PathTrackingDataVisitor implements TweedDataVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitComment(String comment) {
|
||||
delegate.visitComment(comment);
|
||||
public void visitDecoration(TweedDataDecoration decoration) {
|
||||
delegate.visitDecoration(decoration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,6 @@ import org.jspecify.annotations.Nullable;
|
||||
public class PatherExtensionImpl implements PatherExtension, TweedExtension, ReadWriteRelatedExtension {
|
||||
private static final String PATHER_ID = "pather";
|
||||
|
||||
private final Middleware<TweedEntryReader<?, ?>> entryReaderMiddleware = createEntryReaderMiddleware();
|
||||
private final Middleware<TweedEntryWriter<?, ?>> entryWriterMiddleware = createEntryWriterMiddleware();
|
||||
|
||||
private @Nullable PatchworkPartAccess<PathTracking> rwContextPathTrackingAccess;
|
||||
|
||||
@Override
|
||||
@@ -36,6 +33,8 @@ public class PatherExtensionImpl implements PatherExtension, TweedExtension, Rea
|
||||
@Override
|
||||
public void setupReadWriteExtension(ReadWriteExtensionSetupContext context) {
|
||||
rwContextPathTrackingAccess = context.registerReadWriteContextExtensionData(PathTracking.class);
|
||||
context.registerReaderMiddleware(createEntryReaderMiddleware());
|
||||
context.registerWriterMiddleware(createEntryWriterMiddleware());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,14 +143,4 @@ public class PatherExtensionImpl implements PatherExtension, TweedExtension, Rea
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Middleware<TweedEntryReader<?, ?>> entryReaderMiddleware() {
|
||||
return entryReaderMiddleware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Middleware<TweedEntryWriter<?, ?>> entryWriterMiddleware() {
|
||||
return entryWriterMiddleware;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
|
||||
@Override
|
||||
public void setupReadWriteExtension(ReadWriteExtensionSetupContext context) {
|
||||
readContextValidationIssuesAccess = context.registerReadWriteContextExtensionData(ValidationIssues.class);
|
||||
context.registerReaderMiddleware(new EntryValidationReaderMiddleware());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,11 +174,6 @@ public class ValidationExtensionImpl implements ReadWriteRelatedExtension, Valid
|
||||
return entryData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Middleware<TweedEntryReader<?, ?>> entryReaderMiddleware() {
|
||||
return new EntryValidationReaderMiddleware();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ValidationIssues validate(ConfigEntry<T> entry, @Nullable T value) {
|
||||
PathTracking pathTracking = new PathTracking();
|
||||
|
||||
Reference in New Issue
Block a user