[weaver-pojo] Introduce pojo weaver post processors
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
dependencies {
|
||||
api(project(":tweed5-core"))
|
||||
api(project(":tweed5-naming-format"))
|
||||
compileOnly(project(":tweed5-default-extensions"))
|
||||
compileOnly(project(":tweed5-serde-extension"))
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
|
||||
* Marks this class as a class that should be woven as a {@link de.siphalor.tweed5.core.api.entry.CompoundConfigEntry}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
public @interface CompoundWeaving {
|
||||
/**
|
||||
* The naming format to use for this POJO.
|
||||
|
||||
@@ -6,6 +6,7 @@ import de.siphalor.tweed5.core.impl.DefaultConfigContainer;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.CompoundPojoWeaver;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.TrivialPojoWeaver;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeaver;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -22,5 +23,7 @@ public @interface PojoWeaving {
|
||||
TrivialPojoWeaver.class,
|
||||
};
|
||||
|
||||
Class<? extends TweedPojoWeavingPostProcessor>[] postProcessors() default {};
|
||||
|
||||
Class<? extends TweedExtension>[] extensions() default {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents multi-level annotations across multiple Java elements.
|
||||
* E.g. annotations on a field overriding annotations declared on the field type.
|
||||
*/
|
||||
public class Annotations {
|
||||
private static final List<ElementType> ELEMENT_TYPE_ORDER = Arrays.asList(
|
||||
ElementType.TYPE_USE,
|
||||
ElementType.FIELD,
|
||||
ElementType.CONSTRUCTOR,
|
||||
ElementType.METHOD,
|
||||
ElementType.LOCAL_VARIABLE,
|
||||
ElementType.TYPE_PARAMETER,
|
||||
ElementType.TYPE,
|
||||
ElementType.ANNOTATION_TYPE,
|
||||
ElementType.PACKAGE
|
||||
);
|
||||
private final Map<ElementType, AnnotatedElement> elements = new EnumMap<>(ElementType.class);
|
||||
|
||||
public void addAnnotationsFrom(ElementType elementType, AnnotatedElement element) {
|
||||
elements.put(elementType, element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
for (ElementType elementType : ELEMENT_TYPE_ORDER) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement != null) {
|
||||
T annotation = annotatedElement.getAnnotation(annotationClass);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends Annotation> T getAnnotation(ElementType elementType, Class<T> annotationType) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement == null) {
|
||||
return null;
|
||||
}
|
||||
return annotatedElement.getAnnotation(annotationType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <T extends Annotation> T[] getAnnotationHierarchy(Class<T> annotationClass) {
|
||||
List<T> hierarchy = new ArrayList<>(elements.size());
|
||||
for (ElementType elementType : ELEMENT_TYPE_ORDER) {
|
||||
AnnotatedElement element = elements.get(elementType);
|
||||
if (element != null) {
|
||||
T annotation = element.getAnnotation(annotationClass);
|
||||
if (annotation != null) {
|
||||
hierarchy.add(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return hierarchy.toArray((T[]) Array.newInstance(annotationClass, hierarchy.size()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
for (ElementType elementType : ELEMENT_TYPE_ORDER) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement != null) {
|
||||
T[] annotations = annotatedElement.getAnnotationsByType(annotationClass);
|
||||
if (annotations.length != 0) {
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T[]) Array.newInstance(annotationClass, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <T extends Annotation> T[] getAnnotations(ElementType elementType, Class<T> annotationType) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement == null) {
|
||||
//noinspection unchecked
|
||||
return (T[]) Array.newInstance(annotationType, 0);
|
||||
}
|
||||
return annotatedElement.getAnnotationsByType(annotationType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public <T extends Annotation> T[][] getAnnotationsHierachy(Class<T> annotationClass) {
|
||||
List<T[]> hierarchy = new ArrayList<>(ELEMENT_TYPE_ORDER.size());
|
||||
for (ElementType elementType : ELEMENT_TYPE_ORDER) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement != null) {
|
||||
T[] annotations = annotatedElement.getAnnotationsByType(annotationClass);
|
||||
if (annotations.length != 0) {
|
||||
hierarchy.add(annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return hierarchy.toArray((T[][]) Array.newInstance(annotationClass, 0, 0));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Annotation[] getAllAnnotations() {
|
||||
Map<Class<? extends Annotation>, Annotation[]> annotations = new HashMap<>();
|
||||
for (ElementType elementType : ELEMENT_TYPE_ORDER) {
|
||||
AnnotatedElement annotatedElement = elements.get(elementType);
|
||||
if (annotatedElement != null) {
|
||||
for (Annotation annotation : annotatedElement.getAnnotations()) {
|
||||
annotations.putIfAbsent(annotation.annotationType(), new Annotation[]{annotation});
|
||||
|
||||
Repeatable repeatable = annotation.annotationType().getAnnotation(Repeatable.class);
|
||||
if (repeatable != null) {
|
||||
annotations.put(repeatable.value(), annotatedElement.getAnnotationsByType(repeatable.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (annotations.isEmpty()) {
|
||||
return new Annotation[0];
|
||||
} else if (annotations.size() == 1) {
|
||||
return annotations.values().iterator().next();
|
||||
} else {
|
||||
return annotations.values().stream().flatMap(Arrays::stream).toArray(Annotation[]::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
||||
|
||||
import de.siphalor.tweed5.core.api.collection.TypedMultimap;
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
|
||||
import de.siphalor.tweed5.namingformat.api.NamingFormat;
|
||||
@@ -8,19 +7,18 @@ import de.siphalor.tweed5.namingformat.api.NamingFormatCollector;
|
||||
import de.siphalor.tweed5.namingformat.api.NamingFormats;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.CompoundWeaving;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.entry.WeavableCompoundConfigEntry;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.entry.StaticPojoCompoundConfigEntry;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoClassIntrospector;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.PojoWeavingException;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.entry.StaticPojoCompoundConfigEntry;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfig;
|
||||
import de.siphalor.tweed5.weaver.pojo.impl.weaving.compound.CompoundWeavingConfigImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A weaver that weaves classes with the {@link CompoundWeaving} annotation as compound entries.
|
||||
@@ -43,11 +41,11 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
||||
|
||||
@Override
|
||||
public @Nullable <T> ConfigEntry<T> weaveEntry(Class<T> valueClass, WeavingContext context) {
|
||||
if (!valueClass.isAnnotationPresent(CompoundWeaving.class)) {
|
||||
if (context.annotations().getAnnotation(CompoundWeaving.class) == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
CompoundWeavingConfig weavingConfig = getOrCreateWeavingConfig(valueClass, context);
|
||||
CompoundWeavingConfig weavingConfig = getOrCreateWeavingConfig(context);
|
||||
WeavingContext.ExtensionsData newExtensionsData = context.extensionsData().copy();
|
||||
weavingConfigAccess.set(newExtensionsData, weavingConfig);
|
||||
|
||||
@@ -68,7 +66,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundWeavingConfig getOrCreateWeavingConfig(Class<?> valueClass, WeavingContext context) {
|
||||
private CompoundWeavingConfig getOrCreateWeavingConfig(WeavingContext context) {
|
||||
CompoundWeavingConfig parent;
|
||||
if (context.extensionsData().isPatchworkPartSet(CompoundWeavingConfig.class)) {
|
||||
parent = (CompoundWeavingConfig) context.extensionsData();
|
||||
@@ -76,7 +74,7 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
||||
parent = DEFAULT_WEAVING_CONFIG;
|
||||
}
|
||||
|
||||
CompoundWeavingConfig local = getWeavingConfigFromClassAnnotation(valueClass);
|
||||
CompoundWeavingConfig local = createWeavingConfigFromAnnotations(context.annotations());
|
||||
if (local == null) {
|
||||
return parent;
|
||||
}
|
||||
@@ -91,23 +89,21 @@ public class CompoundPojoWeaver implements TweedPojoWeaver {
|
||||
WeavingContext parentContext
|
||||
) {
|
||||
return parentContext.subContextBuilder(name)
|
||||
.additionalData(createAdditionalDataFromAnnotations(property.field().getAnnotations()))
|
||||
.annotations(collectAnnotationsForField(property.field()))
|
||||
.extensionsData(newExtensionsData)
|
||||
.build();
|
||||
}
|
||||
|
||||
private TypedMultimap<Object> createAdditionalDataFromAnnotations(Annotation[] annotations) {
|
||||
if (annotations.length == 0) {
|
||||
return TypedMultimap.empty();
|
||||
}
|
||||
TypedMultimap<Object> additionalData = new TypedMultimap<>(new HashMap<>(), ArrayList::new);
|
||||
Collections.addAll(additionalData, annotations);
|
||||
return TypedMultimap.unmodifiable(additionalData);
|
||||
private Annotations collectAnnotationsForField(Field field) {
|
||||
Annotations annotations = new Annotations();
|
||||
annotations.addAnnotationsFrom(ElementType.TYPE, field.getType());
|
||||
annotations.addAnnotationsFrom(ElementType.FIELD, field);
|
||||
return annotations;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CompoundWeavingConfig getWeavingConfigFromClassAnnotation(Class<?> clazz) {
|
||||
CompoundWeaving annotation = clazz.getAnnotation(CompoundWeaving.class);
|
||||
private CompoundWeavingConfig createWeavingConfigFromAnnotations(Annotations annotations) {
|
||||
CompoundWeaving annotation = annotations.getAnnotation(CompoundWeaving.class);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
||||
|
||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.patchwork.api.Patchwork;
|
||||
import de.siphalor.tweed5.core.api.collection.TypedMultimap;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -14,26 +14,30 @@ import java.util.Arrays;
|
||||
public class WeavingContext implements TweedPojoWeavingFunction.NonNull {
|
||||
@Nullable
|
||||
WeavingContext parent;
|
||||
ExtensionsData extensionsData;
|
||||
@Getter(AccessLevel.NONE)
|
||||
@NotNull
|
||||
TweedPojoWeavingFunction.NonNull weavingFunction;
|
||||
@NotNull
|
||||
ConfigContainer<?> configContainer;
|
||||
@NotNull
|
||||
String[] path;
|
||||
TypedMultimap<Object> additionalData;
|
||||
@NotNull
|
||||
ExtensionsData extensionsData;
|
||||
@NotNull
|
||||
Annotations annotations;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder(null, new String[0]);
|
||||
public static Builder builder(TweedPojoWeavingFunction.NonNull weavingFunction, ConfigContainer<?> configContainer) {
|
||||
return new Builder(null, weavingFunction, configContainer, new String[0]);
|
||||
}
|
||||
|
||||
public static Builder builder(String baseName) {
|
||||
return new Builder(null, new String[]{ baseName });
|
||||
public static Builder builder(TweedPojoWeavingFunction.NonNull weavingFunction, ConfigContainer<?> configContainer, String baseName) {
|
||||
return new Builder(null, weavingFunction, configContainer, new String[]{ baseName });
|
||||
}
|
||||
|
||||
public Builder subContextBuilder(String subPathName) {
|
||||
String[] newPath = Arrays.copyOf(path, path.length + 1);
|
||||
newPath[path.length] = subPathName;
|
||||
return new Builder(this, newPath)
|
||||
.extensionsData(extensionsData)
|
||||
.weavingFunction(weavingFunction);
|
||||
return new Builder(this, weavingFunction, configContainer, newPath).extensionsData(extensionsData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,18 +53,20 @@ public class WeavingContext implements TweedPojoWeavingFunction.NonNull {
|
||||
public static class Builder {
|
||||
@Nullable
|
||||
private final WeavingContext parent;
|
||||
private final TweedPojoWeavingFunction.NonNull weavingFunction;
|
||||
private final ConfigContainer<?> configContainer;
|
||||
private final String[] path;
|
||||
private ExtensionsData extensionsData;
|
||||
private TweedPojoWeavingFunction.NonNull weavingFunction;
|
||||
private TypedMultimap<Object> additionalData;
|
||||
private Annotations annotations;
|
||||
|
||||
public WeavingContext build() {
|
||||
return new WeavingContext(
|
||||
parent,
|
||||
extensionsData,
|
||||
weavingFunction,
|
||||
configContainer,
|
||||
path,
|
||||
additionalData
|
||||
extensionsData,
|
||||
annotations
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess;
|
||||
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
||||
|
||||
public interface TweedPojoWeavingPostProcessor {
|
||||
void apply(ConfigEntry<?> configEntry, WeavingContext context);
|
||||
}
|
||||
@@ -9,13 +9,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StaticPojoCompoundConfigEntry<T> extends BaseConfigEntry<T> implements WeavableCompoundConfigEntry<T> {
|
||||
private final MethodHandle noArgsConstructor;
|
||||
private final Map<String, SubEntry> subEntries = new HashMap<>();
|
||||
private final Map<String, ConfigEntry<?>> subConfigEntries = new HashMap<>();
|
||||
private final Map<String, SubEntry> subEntries = new LinkedHashMap<>();
|
||||
private final Map<String, ConfigEntry<?>> subConfigEntries = new LinkedHashMap<>();
|
||||
|
||||
public StaticPojoCompoundConfigEntry(@NotNull Class<T> valueClass, @NotNull MethodHandle noArgsConstructor) {
|
||||
super(valueClass);
|
||||
@@ -67,7 +67,7 @@ public class StaticPojoCompoundConfigEntry<T> extends BaseConfigEntry<T> impleme
|
||||
public T instantiateCompoundValue() {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (T) noArgsConstructor.invokeExact();
|
||||
return (T) noArgsConstructor.invoke();
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException("Failed to instantiate compound class", e);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@@ -46,7 +46,7 @@ public class PojoClassIntrospector {
|
||||
|
||||
public Map<String, Property> properties() {
|
||||
if (this.properties == null) {
|
||||
this.properties = new HashMap<>();
|
||||
this.properties = new LinkedHashMap<>();
|
||||
Class<?> currentClass = clazz;
|
||||
while (currentClass != null) {
|
||||
appendClassProperties(currentClass);
|
||||
|
||||
@@ -8,27 +8,36 @@ import de.siphalor.tweed5.patchwork.api.PatchworkClassCreator;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClass;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassGenerator;
|
||||
import de.siphalor.tweed5.patchwork.impl.PatchworkClassPart;
|
||||
import de.siphalor.tweed5.utils.api.collection.ClassToInstancesMultimap;
|
||||
import de.siphalor.tweed5.utils.api.collection.InheritanceMap;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.annotation.PojoWeaving;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.Annotations;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeaver;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
|
||||
import de.siphalor.tweed5.weaver.pojo.api.weaving.postprocess.TweedPojoWeavingPostProcessor;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A class that sets up and handles all the bits and bobs for weaving a {@link ConfigContainer} out of a POJO.
|
||||
* The POJO must be annotated with {@link PojoWeaving}.
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class TweedPojoWeaverBootstrapper<T> {
|
||||
private final Class<T> pojoClass;
|
||||
private final ConfigContainer<T> configContainer;
|
||||
private final Collection<TweedPojoWeaver> weavers;
|
||||
private final Collection<TweedPojoWeavingPostProcessor> postProcessors;
|
||||
private PatchworkClass<WeavingContext.ExtensionsData> contextExtensionsDataClass;
|
||||
|
||||
public static <T> TweedPojoWeaverBootstrapper<T> create(Class<T> pojoClass) {
|
||||
@@ -37,11 +46,14 @@ public class TweedPojoWeaverBootstrapper<T> {
|
||||
//noinspection unchecked
|
||||
ConfigContainer<T> configContainer = (ConfigContainer<T>) createConfigContainer((Class<? extends ConfigContainer<?>>) rootWeavingConfig.container());
|
||||
|
||||
Collection<TweedPojoWeaver> weavers = loadWeavers(Arrays.asList(rootWeavingConfig.weavers()));
|
||||
Collection<TweedPojoWeavingPostProcessor> postProcessors = loadPostProcessors(Arrays.asList(rootWeavingConfig.postProcessors()));
|
||||
|
||||
Collection<TweedExtension> extensions = loadExtensions(Arrays.asList(rootWeavingConfig.extensions()));
|
||||
configContainer.registerExtensions(extensions.toArray(new TweedExtension[0]));
|
||||
configContainer.finishExtensionSetup();
|
||||
|
||||
return new TweedPojoWeaverBootstrapper<>(pojoClass, configContainer, loadWeavers(Arrays.asList(rootWeavingConfig.weavers())));
|
||||
return new TweedPojoWeaverBootstrapper<>(pojoClass, configContainer, weavers, postProcessors);
|
||||
}
|
||||
|
||||
private static Collection<TweedExtension> loadExtensions(Collection<Class<? extends TweedExtension>> extensionClasses) {
|
||||
@@ -53,11 +65,15 @@ public class TweedPojoWeaverBootstrapper<T> {
|
||||
}
|
||||
|
||||
private static Collection<TweedPojoWeaver> loadWeavers(Collection<Class<? extends TweedPojoWeaver>> weaverClasses) {
|
||||
List<TweedPojoWeaver> weavers = new ArrayList<>();
|
||||
for (Class<? extends TweedPojoWeaver> weaverClass : weaverClasses) {
|
||||
weavers.add(checkImplementsAndInstantiate(TweedPojoWeaver.class, weaverClass));
|
||||
}
|
||||
return weavers;
|
||||
return weaverClasses.stream()
|
||||
.map(weaverClass -> checkImplementsAndInstantiate(TweedPojoWeaver.class, weaverClass))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Collection<TweedPojoWeavingPostProcessor> loadPostProcessors(Collection<Class<? extends TweedPojoWeavingPostProcessor>> postProcessorClasses) {
|
||||
return postProcessorClasses.stream()
|
||||
.map(postProcessorClass -> checkImplementsAndInstantiate(TweedPojoWeavingPostProcessor.class, postProcessorClass))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static ConfigContainer<?> createConfigContainer(Class<? extends ConfigContainer<?>> containerClass) {
|
||||
@@ -197,9 +213,13 @@ public class TweedPojoWeaverBootstrapper<T> {
|
||||
private WeavingContext createWeavingContext() {
|
||||
try {
|
||||
WeavingContext.ExtensionsData extensionsData = (WeavingContext.ExtensionsData) contextExtensionsDataClass.constructor().invoke();
|
||||
return WeavingContext.builder()
|
||||
|
||||
Annotations annotations = new Annotations();
|
||||
annotations.addAnnotationsFrom(ElementType.TYPE, pojoClass);
|
||||
|
||||
return WeavingContext.builder(this::weaveEntry, configContainer)
|
||||
.extensionsData(extensionsData)
|
||||
.weavingFunction(this::weaveEntry)
|
||||
.annotations(annotations)
|
||||
.build();
|
||||
} catch (Throwable e) {
|
||||
throw new PojoWeavingException("Failed to create weaving context's extension data");
|
||||
@@ -210,7 +230,10 @@ public class TweedPojoWeaverBootstrapper<T> {
|
||||
for (TweedPojoWeaver weaver : weavers) {
|
||||
ConfigEntry<U> configEntry = weaver.weaveEntry(dataClass, context);
|
||||
if (configEntry != null) {
|
||||
configEntry.seal(configContainer);
|
||||
if (!configEntry.sealed()) {
|
||||
configEntry.seal(configContainer);
|
||||
}
|
||||
applyPostProcessors(configEntry, context);
|
||||
return configEntry;
|
||||
}
|
||||
}
|
||||
@@ -218,6 +241,16 @@ public class TweedPojoWeaverBootstrapper<T> {
|
||||
throw new PojoWeavingException("Failed to weave " + dataClass.getName() + ": No matching weavers found");
|
||||
}
|
||||
|
||||
private void applyPostProcessors(ConfigEntry<?> configEntry, WeavingContext context) {
|
||||
for (TweedPojoWeavingPostProcessor postProcessor : postProcessors) {
|
||||
try {
|
||||
postProcessor.apply(configEntry, context);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to apply Tweed POJO weaver post processor", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Setter
|
||||
private static class RegisteredExtensionDataImpl<E> implements RegisteredExtensionData<WeavingContext.ExtensionsData, E> {
|
||||
private MethodHandle setter;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.siphalor.tweed5.weaver.pojo.api.weaving;
|
||||
|
||||
import de.siphalor.tweed5.core.api.container.ConfigContainer;
|
||||
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.entry.SimpleConfigEntry;
|
||||
import de.siphalor.tweed5.core.api.extension.RegisteredExtensionData;
|
||||
@@ -12,6 +13,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
import static de.siphalor.tweed5.weaver.pojo.test.ConfigEntryAssertions.isCompoundEntryForClassWith;
|
||||
import static de.siphalor.tweed5.weaver.pojo.test.ConfigEntryAssertions.isSimpleEntryForClass;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -30,9 +33,10 @@ class CompoundPojoWeaverTest {
|
||||
}
|
||||
});
|
||||
|
||||
WeavingContext weavingContext = WeavingContext.builder()
|
||||
.extensionsData(new ExtensionsDataMock(null))
|
||||
.weavingFunction(new TweedPojoWeavingFunction.NonNull() {
|
||||
Annotations annotations = new Annotations();
|
||||
annotations.addAnnotationsFrom(ElementType.TYPE, Compound.class);
|
||||
|
||||
WeavingContext weavingContext = WeavingContext.builder(new TweedPojoWeavingFunction.NonNull() {
|
||||
@Override
|
||||
public @NotNull <T> ConfigEntry<T> weaveEntry(Class<T> valueClass, WeavingContext context) {
|
||||
ConfigEntry<T> entry = compoundWeaver.weaveEntry(valueClass, context);
|
||||
@@ -45,7 +49,9 @@ class CompoundPojoWeaverTest {
|
||||
return configEntry;
|
||||
}
|
||||
}
|
||||
})
|
||||
}, mock(ConfigContainer.class))
|
||||
.extensionsData(new ExtensionsDataMock(null))
|
||||
.annotations(annotations)
|
||||
.build();
|
||||
|
||||
ConfigEntry<Compound> resultEntry = compoundWeaver.weaveEntry(Compound.class, weavingContext);
|
||||
|
||||
Reference in New Issue
Block a user