feat(weaver-pojo): Proper API for POJO weaving
This commit is contained in:
@@ -9,7 +9,7 @@ import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
|||||||
import de.siphalor.tweed5.data.hjson.HjsonSerde;
|
import de.siphalor.tweed5.data.hjson.HjsonSerde;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
||||||
import de.siphalor.tweed5.fabric.helper.api.FabricConfigContainerHelper;
|
import de.siphalor.tweed5.fabric.helper.api.FabricConfigContainerHelper;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import lombok.CustomLog;
|
import lombok.CustomLog;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
@@ -35,7 +35,7 @@ public class TweedCoatBridgeTestMod implements ClientModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
configContainer = TweedPojoWeaverBootstrapper.create(TweedCoatBridgeTestModConfig.class).weave();
|
configContainer = TweedPojoWeaver.forClass(TweedCoatBridgeTestModConfig.class).weave();
|
||||||
configCoatBridgeExtension = configContainer.extension(TweedCoatBridgeExtension.class)
|
configCoatBridgeExtension = configContainer.extension(TweedCoatBridgeExtension.class)
|
||||||
.orElseThrow(() -> new IllegalStateException("TweedCoatBridgeExtension not found"));
|
.orElseThrow(() -> new IllegalStateException("TweedCoatBridgeExtension not found"));
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import de.siphalor.tweed5.data.hjson.HjsonSerde;
|
|||||||
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
||||||
import de.siphalor.tweed5.fabric.helper.api.FabricConfigCommentLoader;
|
import de.siphalor.tweed5.fabric.helper.api.FabricConfigCommentLoader;
|
||||||
import de.siphalor.tweed5.fabric.helper.api.FabricConfigContainerHelper;
|
import de.siphalor.tweed5.fabric.helper.api.FabricConfigContainerHelper;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import lombok.CustomLog;
|
import lombok.CustomLog;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
@@ -22,7 +22,7 @@ public class FabricHelperTestMod implements ModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
configContainer = TweedPojoWeaverBootstrapper.create(TestModConfig.class).weave();
|
configContainer = TweedPojoWeaver.forClass(TestModConfig.class).weave();
|
||||||
configFilterExtension = configContainer.extension(AttributesReadWriteFilterExtension.class)
|
configFilterExtension = configContainer.extension(AttributesReadWriteFilterExtension.class)
|
||||||
.orElseThrow(() -> new IllegalStateException("AttributesReadWriteFilterExtension not found"));
|
.orElseThrow(() -> new IllegalStateException("AttributesReadWriteFilterExtension not found"));
|
||||||
configFilterExtension.markAttributeForFiltering("reload");
|
configFilterExtension.markAttributeForFiltering("reload");
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import de.siphalor.tweed5.attributesextension.api.AttributesExtension;
|
|||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -16,7 +16,7 @@ import static org.assertj.core.api.InstanceOfAssertFactories.type;
|
|||||||
class AttributesPojoWeavingProcessorTest {
|
class AttributesPojoWeavingProcessorTest {
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
ConfigContainer<Config> configContainer = TweedPojoWeaverBootstrapper.create(Config.class).weave();
|
ConfigContainer<Config> configContainer = TweedPojoWeaver.forClass(Config.class).weave();
|
||||||
configContainer.initialize();
|
configContainer.initialize();
|
||||||
|
|
||||||
AttributesExtension attributesExtension = configContainer.extension(AttributesExtension.class).orElseThrow();
|
AttributesExtension attributesExtension = configContainer.extension(AttributesExtension.class).orElseThrow();
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
|||||||
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.CompoundConfigEntry;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension;
|
import de.siphalor.tweed5.defaultextensions.presets.api.PresetsExtension;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@@ -20,7 +20,7 @@ class PresetsWeavingProcessorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
ConfigContainer<Config> configContainer = TweedPojoWeaverBootstrapper.create(Config.class).weave();
|
ConfigContainer<Config> configContainer = TweedPojoWeaver.forClass(Config.class).weave();
|
||||||
configContainer.initialize();
|
configContainer.initialize();
|
||||||
PresetsExtension presetsExtension = configContainer.extension(PresetsExtension.class).orElseThrow();
|
PresetsExtension presetsExtension = configContainer.extension(PresetsExtension.class).orElseThrow();
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,18 @@ package de.siphalor.tweed5.weaver.pojoext.serde.api;
|
|||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.data.extension.api.*;
|
import de.siphalor.tweed5.data.extension.api.ReadWriteExtension;
|
||||||
|
import de.siphalor.tweed5.data.extension.api.TweedEntryWriter;
|
||||||
|
import de.siphalor.tweed5.data.extension.api.TweedReaderWriterProvider;
|
||||||
|
import de.siphalor.tweed5.data.extension.api.TweedWriteContext;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonLexer;
|
import de.siphalor.tweed5.data.hjson.HjsonLexer;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonReader;
|
import de.siphalor.tweed5.data.hjson.HjsonReader;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
import de.siphalor.tweed5.dataapi.api.TweedDataVisitor;
|
||||||
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
import de.siphalor.tweed5.dataapi.api.TweedDataWriteException;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverImpl;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -27,10 +31,7 @@ class ReadWritePojoWeavingProcessorTest {
|
|||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
void testAnnotated() {
|
void testAnnotated() {
|
||||||
TweedPojoWeaverBootstrapper<AnnotatedConfig> weaverBootstrapper = TweedPojoWeaverBootstrapper.create(
|
ConfigContainer<AnnotatedConfig> configContainer = TweedPojoWeaver.forClass(AnnotatedConfig.class).weave();
|
||||||
AnnotatedConfig.class);
|
|
||||||
|
|
||||||
ConfigContainer<AnnotatedConfig> configContainer = weaverBootstrapper.weave();
|
|
||||||
configContainer.initialize();
|
configContainer.initialize();
|
||||||
|
|
||||||
AnnotatedConfig config = new AnnotatedConfig(123, "test", new TestClass(987));
|
AnnotatedConfig config = new AnnotatedConfig(123, "test", new TestClass(987));
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import de.siphalor.tweed5.data.extension.api.ReadWriteExtension;
|
|||||||
import de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriter;
|
import de.siphalor.tweed5.data.extension.api.readwrite.TweedEntryReaderWriter;
|
||||||
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.NullablePojoWeaver;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.NullablePojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverImpl;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jspecify.annotations.NullUnmarked;
|
import org.jspecify.annotations.NullUnmarked;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -33,9 +34,7 @@ class AutoReadWritePojoWeavingProcessorTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
var bootstrapper = TweedPojoWeaverBootstrapper.create(AnnotatedConfig.class);
|
container = TweedPojoWeaver.forClass(AnnotatedConfig.class).weave();
|
||||||
|
|
||||||
container = bootstrapper.weave();
|
|
||||||
container.initialize();
|
container.initialize();
|
||||||
|
|
||||||
readWriteExtension = container.extension(ReadWriteExtension.class).orElseThrow();
|
readWriteExtension = container.extension(ReadWriteExtension.class).orElseThrow();
|
||||||
@@ -77,9 +76,7 @@ class AutoReadWritePojoWeavingProcessorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUsage() {
|
void testUsage() {
|
||||||
var bootstrapper = TweedPojoWeaverBootstrapper.create(AnnotatedConfig.class);
|
var container = TweedPojoWeaver.forClass(AnnotatedConfig.class).weave();
|
||||||
|
|
||||||
var container = bootstrapper.weave();
|
|
||||||
container.initialize();
|
container.initialize();
|
||||||
|
|
||||||
AnnotatedConfig config = new AnnotatedConfig()
|
AnnotatedConfig config = new AnnotatedConfig()
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import de.siphalor.tweed5.data.extension.api.TweedEntryWriteException;
|
|||||||
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
import de.siphalor.tweed5.data.extension.impl.TweedEntryReaderWriterImpls;
|
||||||
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
import de.siphalor.tweed5.data.hjson.HjsonWriter;
|
||||||
import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
|
import de.siphalor.tweed5.defaultextensions.pather.api.PatherExtension;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverImpl;
|
||||||
import de.siphalor.tweed5.weaver.pojoext.serde.api.ReadWritePojoWeavingProcessor;
|
import de.siphalor.tweed5.weaver.pojoext.serde.api.ReadWritePojoWeavingProcessor;
|
||||||
import de.siphalor.tweed5.weaver.pojoext.serde.api.auto.AutoReadWritePojoWeavingProcessor;
|
import de.siphalor.tweed5.weaver.pojoext.serde.api.auto.AutoReadWritePojoWeavingProcessor;
|
||||||
import de.siphalor.tweed5.weaver.pojoext.serde.api.auto.DefaultReadWriteMappings;
|
import de.siphalor.tweed5.weaver.pojoext.serde.api.auto.DefaultReadWriteMappings;
|
||||||
@@ -34,9 +35,7 @@ class AutoNullableReadWritePojoWeavingProcessorTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
var bootstrapper = TweedPojoWeaverBootstrapper.create(AnnotatedConfig.class);
|
container = TweedPojoWeaver.forClass(AnnotatedConfig.class).weave();
|
||||||
|
|
||||||
container = bootstrapper.weave();
|
|
||||||
container.initialize();
|
container.initialize();
|
||||||
|
|
||||||
readWriteExtension = container.extension(ReadWriteExtension.class).orElseThrow();
|
readWriteExtension = container.extension(ReadWriteExtension.class).orElseThrow();
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package de.siphalor.tweed5.weaver.pojoext.validation.api;
|
|||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension;
|
import de.siphalor.tweed5.defaultextensions.validation.api.ValidationExtension;
|
||||||
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues;
|
import de.siphalor.tweed5.defaultextensions.validation.api.result.ValidationIssues;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverBootstrapper;
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverImpl;
|
||||||
import de.siphalor.tweed5.weaver.pojoext.validation.api.validators.WeavableNumberRangeValidator;
|
import de.siphalor.tweed5.weaver.pojoext.validation.api.validators.WeavableNumberRangeValidator;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -19,8 +20,7 @@ class ValidatorsPojoWeavingProcessorTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@CsvSource({"-1,true", "0,false", "50,false", "99,false", "100,true", "101,true"})
|
@CsvSource({"-1,true", "0,false", "50,false", "99,false", "100,true", "101,true"})
|
||||||
void test(int value, boolean issuesExpected) {
|
void test(int value, boolean issuesExpected) {
|
||||||
var bootstrapper = TweedPojoWeaverBootstrapper.create(Config.class);
|
ConfigContainer<Config> configContainer = TweedPojoWeaver.forClass(Config.class).weave();
|
||||||
ConfigContainer<Config> configContainer = bootstrapper.weave();
|
|
||||||
configContainer.initialize();
|
configContainer.initialize();
|
||||||
|
|
||||||
var validationExtension = configContainer.extension(ValidationExtension.class).orElseThrow();
|
var validationExtension = configContainer.extension(ValidationExtension.class).orElseThrow();
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package de.siphalor.tweed5.weaver.pojo.api;
|
||||||
|
|
||||||
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
|
import de.siphalor.tweed5.core.api.extension.TweedExtension;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeavingExtension;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.impl.weaving.TweedPojoWeaverImpl;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
public interface TweedPojoWeaver<T> {
|
||||||
|
static <T> TweedPojoWeaver<T> forClass(Class<T> pojoClass) {
|
||||||
|
return TweedPojoWeaverImpl.implForClass(pojoClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<T> pojoClass();
|
||||||
|
ConfigContainer<T> configContainer();
|
||||||
|
|
||||||
|
@Contract("_ -> this")
|
||||||
|
default TweedPojoWeaver<T> withWeavingExtensions(Class<? extends TweedPojoWeavingExtension>... weavingExtensions) {
|
||||||
|
for (Class<? extends TweedPojoWeavingExtension> weavingExtension : weavingExtensions) {
|
||||||
|
withWeavingExtension(weavingExtension);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract("_ -> this")
|
||||||
|
TweedPojoWeaver<T> withWeavingExtension(Class<? extends TweedPojoWeavingExtension> weavingExtension);
|
||||||
|
|
||||||
|
@Contract("_ -> this")
|
||||||
|
default TweedPojoWeaver<T> withExtensions(Class<? extends TweedExtension>... extensions) {
|
||||||
|
for (Class<? extends TweedExtension> extension : extensions) {
|
||||||
|
withExtension(extension);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract("_ -> this")
|
||||||
|
TweedPojoWeaver<T> withExtension(Class<? extends TweedExtension> extension);
|
||||||
|
|
||||||
|
@Contract("_ -> this")
|
||||||
|
TweedPojoWeaver<T> withConfigContainer(ConfigContainer<T> container);
|
||||||
|
|
||||||
|
ConfigContainer<T> weave();
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
|||||||
|
|
||||||
import de.siphalor.tweed5.annotationinheritance.api.AnnotationInheritanceAwareAnnotatedElement;
|
import de.siphalor.tweed5.annotationinheritance.api.AnnotationInheritanceAwareAnnotatedElement;
|
||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
|
import de.siphalor.tweed5.core.api.container.ConfigContainerSetupPhase;
|
||||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||||
import de.siphalor.tweed5.patchwork.api.Patchwork;
|
import de.siphalor.tweed5.patchwork.api.Patchwork;
|
||||||
import de.siphalor.tweed5.patchwork.api.PatchworkFactory;
|
import de.siphalor.tweed5.patchwork.api.PatchworkFactory;
|
||||||
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
import de.siphalor.tweed5.typeutils.api.type.ActualType;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.PojoWeaving;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.PojoWeaving;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.PojoWeavingExtension;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.PojoWeavingExtension;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.TweedExtension;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.TweedExtension;
|
||||||
@@ -13,6 +15,7 @@ import de.siphalor.tweed5.weaver.pojo.api.weaving.ProtoWeavingContext;
|
|||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeavingExtension;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeavingExtension;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.apachecommons.CommonsLog;
|
import lombok.extern.apachecommons.CommonsLog;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -21,6 +24,8 @@ import java.lang.annotation.Annotation;
|
|||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,11 +34,18 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
@CommonsLog
|
@CommonsLog
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class TweedPojoWeaverBootstrapper<T> {
|
public class TweedPojoWeaverImpl<T> implements TweedPojoWeaver<T> {
|
||||||
|
@Getter
|
||||||
private final Class<T> pojoClass;
|
private final Class<T> pojoClass;
|
||||||
private final AnnotatedElement pojoAnnotations;
|
private final AnnotatedElement pojoAnnotations;
|
||||||
private final ConfigContainer<T> configContainer;
|
private final PojoWeaving rootWeavingConfig;
|
||||||
private final Collection<TweedPojoWeavingExtension> weavingExtensions;
|
|
||||||
|
private final Set<Class<? extends TweedPojoWeavingExtension>> weavingExtensionClasses = new HashSet<>();
|
||||||
|
private @Nullable Collection<TweedPojoWeavingExtension> weavingExtensions;
|
||||||
|
|
||||||
|
private @Nullable ConfigContainer<T> configContainer;
|
||||||
|
private final Set<Class<? extends de.siphalor.tweed5.core.api.extension.TweedExtension>> extensionClasses = new HashSet<>();
|
||||||
|
|
||||||
private final WeavingContext.WeavingFn weavingContextFn = new WeavingContext.WeavingFn() {
|
private final WeavingContext.WeavingFn weavingContextFn = new WeavingContext.WeavingFn() {
|
||||||
@Override
|
@Override
|
||||||
public <U> ConfigEntry<U> weaveEntry(
|
public <U> ConfigEntry<U> weaveEntry(
|
||||||
@@ -41,61 +53,21 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
Patchwork extensionsData,
|
Patchwork extensionsData,
|
||||||
ProtoWeavingContext context
|
ProtoWeavingContext context
|
||||||
) {
|
) {
|
||||||
return TweedPojoWeaverBootstrapper.this.weaveEntry(valueType, extensionsData, context);
|
return TweedPojoWeaverImpl.this.weaveEntry(valueType, extensionsData, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <U> ConfigEntry<U> weavePseudoEntry(WeavingContext parentContext, String pseudoEntryName, Patchwork extensionsData) {
|
public <U> ConfigEntry<U> weavePseudoEntry(WeavingContext parentContext, String pseudoEntryName, Patchwork extensionsData) {
|
||||||
return TweedPojoWeaverBootstrapper.this.weavePseudoEntry(parentContext, pseudoEntryName, extensionsData);
|
return TweedPojoWeaverImpl.this.weavePseudoEntry(parentContext, pseudoEntryName, extensionsData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@Nullable
|
|
||||||
private PatchworkFactory weavingExtensionsPatchworkFactory;
|
|
||||||
|
|
||||||
public static <T> TweedPojoWeaverBootstrapper<T> create(Class<T> pojoClass) {
|
private @Nullable PatchworkFactory weavingExtensionsPatchworkFactory;
|
||||||
|
|
||||||
|
public static <T> TweedPojoWeaverImpl<T> implForClass(Class<T> pojoClass) {
|
||||||
AnnotatedElement pojoAnnotations = new AnnotationInheritanceAwareAnnotatedElement(pojoClass);
|
AnnotatedElement pojoAnnotations = new AnnotationInheritanceAwareAnnotatedElement(pojoClass);
|
||||||
PojoWeaving rootWeavingConfig = expectAnnotation(pojoAnnotations, PojoWeaving.class);
|
PojoWeaving rootWeavingConfig = expectAnnotation(pojoAnnotations, PojoWeaving.class);
|
||||||
PojoWeavingExtension[] extensionAnnotations = pojoAnnotations.getAnnotationsByType(PojoWeavingExtension.class);
|
return new TweedPojoWeaverImpl<>(pojoClass, pojoAnnotations, rootWeavingConfig);
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
ConfigContainer<T>
|
|
||||||
configContainer
|
|
||||||
= (ConfigContainer<T>) createConfigContainer((Class<? extends ConfigContainer<?>>) rootWeavingConfig.container());
|
|
||||||
|
|
||||||
TweedExtension[] tweedExtensions = pojoAnnotations.getAnnotationsByType(TweedExtension.class);
|
|
||||||
//noinspection unchecked
|
|
||||||
configContainer.registerExtensions(
|
|
||||||
Arrays.stream(tweedExtensions).map(TweedExtension::value).toArray(Class[]::new)
|
|
||||||
);
|
|
||||||
configContainer.finishExtensionSetup();
|
|
||||||
|
|
||||||
Collection<TweedPojoWeavingExtension> extensions = loadWeavingExtensions(
|
|
||||||
Arrays.stream(extensionAnnotations).map(PojoWeavingExtension::value).collect(Collectors.toList()),
|
|
||||||
configContainer
|
|
||||||
);
|
|
||||||
|
|
||||||
return new TweedPojoWeaverBootstrapper<>(pojoClass, pojoAnnotations, configContainer, extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Collection<TweedPojoWeavingExtension> loadWeavingExtensions(
|
|
||||||
Collection<Class<? extends TweedPojoWeavingExtension>> weaverClasses,
|
|
||||||
ConfigContainer<?> configContainer
|
|
||||||
) {
|
|
||||||
return weaverClasses.stream()
|
|
||||||
.map(weaverClass ->
|
|
||||||
TweedPojoWeavingExtension.FACTORY.construct(weaverClass)
|
|
||||||
.typedArg(ConfigContainer.class, configContainer)
|
|
||||||
.finish()
|
|
||||||
)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ConfigContainer<?> createConfigContainer(Class<? extends ConfigContainer<?>> containerClass) {
|
|
||||||
try {
|
|
||||||
return ConfigContainer.FACTORY.construct(containerClass).finish();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new PojoWeavingException("Failed to instantiate config container");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <A extends Annotation> A expectAnnotation(AnnotatedElement element, Class<A> annotationClass) {
|
private static <A extends Annotation> A expectAnnotation(AnnotatedElement element, Class<A> annotationClass) {
|
||||||
@@ -110,14 +82,84 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigContainer<T> weave() {
|
@Override
|
||||||
setupWeavingExtensions();
|
public TweedPojoWeaver<T> withConfigContainer(ConfigContainer<T> container) {
|
||||||
|
if (configContainer != null) {
|
||||||
|
throw new IllegalStateException("Config container already set");
|
||||||
|
}
|
||||||
|
this.configContainer = container;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
assert weavingExtensionsPatchworkFactory != null;
|
@Override
|
||||||
|
public ConfigContainer<T> configContainer() {
|
||||||
|
if (configContainer != null) {
|
||||||
|
return configContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
this.configContainer
|
||||||
|
= (ConfigContainer<T>) createConfigContainer((Class<? extends ConfigContainer<?>>) rootWeavingConfig.container());
|
||||||
|
|
||||||
|
for (TweedExtension annotation : pojoAnnotations.getAnnotationsByType(TweedExtension.class)) {
|
||||||
|
extensionClasses.add(annotation.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
configContainer.registerExtensions(extensionClasses.toArray(new Class[0]));
|
||||||
|
|
||||||
|
return configContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConfigContainer<?> createConfigContainer(Class<? extends ConfigContainer<?>> containerClass) {
|
||||||
|
try {
|
||||||
|
return ConfigContainer.FACTORY.construct(containerClass).finish();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PojoWeavingException("Failed to instantiate config container");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TweedPojoWeaver<T> withWeavingExtension(Class<? extends TweedPojoWeavingExtension> weavingExtension) {
|
||||||
|
if (configContainer != null
|
||||||
|
&& configContainer.setupPhase().compareTo(ConfigContainerSetupPhase.TREE_ATTACHED) >= 0) {
|
||||||
|
throw new IllegalStateException("Cannot add weaving extensions after the tree has been attached");
|
||||||
|
}
|
||||||
|
|
||||||
|
weavingExtensionClasses.add(weavingExtension);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TweedPojoWeaver<T> withExtension(Class<? extends de.siphalor.tweed5.core.api.extension.TweedExtension> extension) {
|
||||||
|
if (configContainer != null
|
||||||
|
&& configContainer.setupPhase().compareTo(ConfigContainerSetupPhase.EXTENSIONS_SETUP) > 0) {
|
||||||
|
throw new IllegalStateException("Cannot add extensions after the extensions have been finalized");
|
||||||
|
}
|
||||||
|
|
||||||
|
extensionClasses.add(extension);
|
||||||
|
|
||||||
|
if (configContainer != null) {
|
||||||
|
configContainer.registerExtension(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigContainer<T> weave() {
|
||||||
|
ConfigContainer<T> configContainer = configContainer();
|
||||||
|
|
||||||
|
if (configContainer.setupPhase().compareTo(ConfigContainerSetupPhase.TREE_ATTACHED) >= 0) {
|
||||||
|
throw new IllegalStateException("Cannot weave twice");
|
||||||
|
}
|
||||||
|
if (configContainer.setupPhase() == ConfigContainerSetupPhase.EXTENSIONS_SETUP) {
|
||||||
|
configContainer.finishExtensionSetup();
|
||||||
|
}
|
||||||
|
|
||||||
ConfigEntry<T> rootEntry = this.weaveEntry(
|
ConfigEntry<T> rootEntry = this.weaveEntry(
|
||||||
ActualType.ofClass(pojoClass),
|
ActualType.ofClass(pojoClass),
|
||||||
weavingExtensionsPatchworkFactory.create(),
|
weavingExtensionsPatchworkFactory().create(),
|
||||||
ProtoWeavingContext.create(configContainer, pojoAnnotations)
|
ProtoWeavingContext.create(configContainer, pojoAnnotations)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -128,16 +170,41 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
return configContainer;
|
return configContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupWeavingExtensions() {
|
private PatchworkFactory weavingExtensionsPatchworkFactory() {
|
||||||
|
if (weavingExtensionsPatchworkFactory != null) {
|
||||||
|
return weavingExtensionsPatchworkFactory;
|
||||||
|
}
|
||||||
|
|
||||||
PatchworkFactory.Builder weavingExtensionsPatchworkFactoryBuilder = PatchworkFactory.builder();
|
PatchworkFactory.Builder weavingExtensionsPatchworkFactoryBuilder = PatchworkFactory.builder();
|
||||||
|
|
||||||
TweedPojoWeavingExtension.SetupContext setupContext = weavingExtensionsPatchworkFactoryBuilder::registerPart;
|
TweedPojoWeavingExtension.SetupContext setupContext = weavingExtensionsPatchworkFactoryBuilder::registerPart;
|
||||||
|
|
||||||
for (TweedPojoWeavingExtension weaver : weavingExtensions) {
|
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions()) {
|
||||||
weaver.setup(setupContext);
|
weavingExtension.setup(setupContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
weavingExtensionsPatchworkFactory = weavingExtensionsPatchworkFactoryBuilder.build();
|
weavingExtensionsPatchworkFactory = weavingExtensionsPatchworkFactoryBuilder.build();
|
||||||
|
|
||||||
|
return weavingExtensionsPatchworkFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<TweedPojoWeavingExtension> weavingExtensions() {
|
||||||
|
if (weavingExtensions != null) {
|
||||||
|
return weavingExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PojoWeavingExtension annotation : pojoAnnotations.getAnnotationsByType(PojoWeavingExtension.class)) {
|
||||||
|
weavingExtensionClasses.add(annotation.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
weavingExtensions = weavingExtensionClasses.stream()
|
||||||
|
.map(weavingExtensionClass ->
|
||||||
|
TweedPojoWeavingExtension.FACTORY.construct(weavingExtensionClass)
|
||||||
|
.typedArg(ConfigContainer.class, configContainer)
|
||||||
|
.finish()
|
||||||
|
)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return weavingExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <U> ConfigEntry<U> weaveEntry(
|
private <U> ConfigEntry<U> weaveEntry(
|
||||||
@@ -145,6 +212,8 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
Patchwork extensionsData,
|
Patchwork extensionsData,
|
||||||
ProtoWeavingContext protoContext
|
ProtoWeavingContext protoContext
|
||||||
) {
|
) {
|
||||||
|
assert configContainer != null && weavingExtensions != null;
|
||||||
|
|
||||||
extensionsData = extensionsData.copy();
|
extensionsData = extensionsData.copy();
|
||||||
|
|
||||||
runBeforeWeaveEntryHooks(valueType, extensionsData, protoContext);
|
runBeforeWeaveEntryHooks(valueType, extensionsData, protoContext);
|
||||||
@@ -191,6 +260,8 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
String pseudoEntryName,
|
String pseudoEntryName,
|
||||||
Patchwork extensionsData
|
Patchwork extensionsData
|
||||||
) {
|
) {
|
||||||
|
assert configContainer != null && weavingExtensions != null;
|
||||||
|
|
||||||
extensionsData = extensionsData.copy();
|
extensionsData = extensionsData.copy();
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
@@ -237,6 +308,8 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
Patchwork extensionsData,
|
Patchwork extensionsData,
|
||||||
ProtoWeavingContext protoContext
|
ProtoWeavingContext protoContext
|
||||||
) {
|
) {
|
||||||
|
assert weavingExtensions != null;
|
||||||
|
|
||||||
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
||||||
try {
|
try {
|
||||||
weavingExtension.beforeWeaveEntry(dataClass, extensionsData, protoContext);
|
weavingExtension.beforeWeaveEntry(dataClass, extensionsData, protoContext);
|
||||||
@@ -251,6 +324,8 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <U> void runAfterWeaveEntryHooks(ActualType<U> dataClass, ConfigEntry<U> configEntry, WeavingContext context) {
|
private <U> void runAfterWeaveEntryHooks(ActualType<U> dataClass, ConfigEntry<U> configEntry, WeavingContext context) {
|
||||||
|
assert weavingExtensions != null;
|
||||||
|
|
||||||
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
||||||
try {
|
try {
|
||||||
weavingExtension.afterWeaveEntry(dataClass, configEntry, context);
|
weavingExtension.afterWeaveEntry(dataClass, configEntry, context);
|
||||||
@@ -265,6 +340,8 @@ public class TweedPojoWeaverBootstrapper<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runAfterWeaveHooks() {
|
private void runAfterWeaveHooks() {
|
||||||
|
assert weavingExtensions != null;
|
||||||
|
|
||||||
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
for (TweedPojoWeavingExtension weavingExtension : weavingExtensions) {
|
||||||
weavingExtension.afterWeave();
|
weavingExtension.afterWeave();
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
@NullMarked
|
@NullMarked
|
||||||
|
@ApiStatus.Internal
|
||||||
package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jspecify.annotations.NullMarked;
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
package de.siphalor.tweed5.weaver.pojo.impl.weaving;
|
||||||
|
|
||||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||||
|
import de.siphalor.tweed5.weaver.pojo.api.TweedPojoWeaver;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
import de.siphalor.tweed5.weaver.pojo.api.annotation.*;
|
||||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.CollectionPojoWeaver;
|
import de.siphalor.tweed5.weaver.pojo.api.weaving.CollectionPojoWeaver;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -12,11 +13,10 @@ import static de.siphalor.tweed5.weaver.pojo.test.ConfigEntryAssertions.*;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
class TweedPojoWeaverBootstrapperTest {
|
class TweedPojoWeaverImplTest {
|
||||||
@Test
|
@Test
|
||||||
void defaultWeaving() {
|
void defaultWeaving() {
|
||||||
TweedPojoWeaverBootstrapper<MainCompound> bootstrapper = TweedPojoWeaverBootstrapper.create(MainCompound.class);
|
ConfigContainer<MainCompound> configContainer = TweedPojoWeaver.forClass(MainCompound.class).weave();
|
||||||
ConfigContainer<MainCompound> configContainer = bootstrapper.weave();
|
|
||||||
|
|
||||||
assertThat(configContainer.rootEntry()).satisfies(isCompoundEntryForClassWith(MainCompound.class, rootCompound ->
|
assertThat(configContainer.rootEntry()).satisfies(isCompoundEntryForClassWith(MainCompound.class, rootCompound ->
|
||||||
assertThat(rootCompound.subEntries())
|
assertThat(rootCompound.subEntries())
|
||||||
@@ -39,8 +39,7 @@ class TweedPojoWeaverBootstrapperTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void weavingWithList() {
|
void weavingWithList() {
|
||||||
TweedPojoWeaverBootstrapper<CompoundWithList> bootstrapper = TweedPojoWeaverBootstrapper.create(CompoundWithList.class);
|
ConfigContainer<CompoundWithList> configContainer = TweedPojoWeaver.forClass(CompoundWithList.class).weave();
|
||||||
ConfigContainer<CompoundWithList> configContainer = bootstrapper.weave();
|
|
||||||
|
|
||||||
assertThat(configContainer.rootEntry()).satisfies(isCompoundEntryForClassWith(CompoundWithList.class, rootCompound ->
|
assertThat(configContainer.rootEntry()).satisfies(isCompoundEntryForClassWith(CompoundWithList.class, rootCompound ->
|
||||||
assertThat(rootCompound.subEntries())
|
assertThat(rootCompound.subEntries())
|
||||||
Reference in New Issue
Block a user