[attributes] Introduce attributes extensions

This commit is contained in:
2025-07-27 01:18:32 +02:00
parent e4ea5fdfc2
commit c9a609d457
28 changed files with 1627 additions and 3 deletions

View File

@@ -0,0 +1,11 @@
plugins {
id("de.siphalor.tweed5.base-module")
}
dependencies {
api(project(":tweed5-weaver-pojo"))
api(project(":tweed5-attributes-extension"))
testImplementation(project(":tweed5-default-extensions"))
testImplementation(project(":tweed5-serde-hjson"))
}

View File

@@ -0,0 +1,11 @@
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE})
@Repeatable(Attributes.class)
public @interface Attribute {
String key();
String[] values();
}

View File

@@ -0,0 +1,11 @@
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE})
@Repeatable(AttributeDefaults.class)
public @interface AttributeDefault {
String key();
String[] defaultValue();
}

View File

@@ -0,0 +1,12 @@
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE})
public @interface AttributeDefaults {
AttributeDefault[] value();
}

View File

@@ -0,0 +1,12 @@
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE})
public @interface Attributes {
Attribute[] value();
}

View File

@@ -0,0 +1,75 @@
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import de.siphalor.tweed5.attributesextension.api.AttributesExtension;
import de.siphalor.tweed5.core.api.container.ConfigContainer;
import de.siphalor.tweed5.core.api.entry.ConfigEntry;
import de.siphalor.tweed5.typeutils.api.type.ActualType;
import de.siphalor.tweed5.weaver.pojo.api.weaving.TweedPojoWeavingExtension;
import de.siphalor.tweed5.weaver.pojo.api.weaving.WeavingContext;
import lombok.var;
import org.jetbrains.annotations.ApiStatus;
import java.util.*;
import java.util.function.Function;
public class AttributesPojoWeavingProcessor implements TweedPojoWeavingExtension {
AttributesExtension attributesExtension;
@ApiStatus.Internal
public AttributesPojoWeavingProcessor(ConfigContainer<?> configContainer) {
attributesExtension = configContainer.extension(AttributesExtension.class)
.orElseThrow(() -> new IllegalStateException(
"You must register a " + AttributesExtension.class.getSimpleName()
+ " to use the " + getClass().getSimpleName()
));
}
@Override
public void setup(SetupContext context) {
}
@Override
public <T> void afterWeaveEntry(ActualType<T> valueType, ConfigEntry<T> configEntry, WeavingContext context) {
var attributeAnnotations = context.annotations().getAnnotationsByType(Attribute.class);
var attributes = collectAttributesFromAnnotations(attributeAnnotations, Attribute::key, Attribute::values);
attributes.forEach((key, values) -> attributesExtension.setAttribute(configEntry, key, values));
var attributeDefaultAnnotations = context.annotations().getAnnotationsByType(AttributeDefault.class);
var attributeDefaults = collectAttributesFromAnnotations(
attributeDefaultAnnotations,
AttributeDefault::key,
AttributeDefault::defaultValue
);
attributeDefaults.forEach((key, values) -> attributesExtension.setAttributeDefault(configEntry, key, values));
}
private <T> Map<String, List<String>> collectAttributesFromAnnotations(
T[] annotations,
Function<T, String> keyGetter,
Function<T, String[]> valueGetter
) {
if (annotations.length == 0) {
return Collections.emptyMap();
}
Map<String, List<String>> attributes;
if (annotations.length == 1) {
return Collections.singletonMap(
keyGetter.apply(annotations[0]),
Arrays.asList(valueGetter.apply(annotations[0]))
);
} else if (annotations.length <= 12) {
attributes = new TreeMap<>();
} else {
attributes = new HashMap<>();
}
for (T annotation : annotations) {
attributes.computeIfAbsent(keyGetter.apply(annotation), k -> new ArrayList<>())
.addAll(Arrays.asList(valueGetter.apply(annotation)));
}
return attributes;
}
}

View File

@@ -0,0 +1,4 @@
@NullMarked
package de.siphalor.tweed5.weaver.pojoext.attributes.api;
import org.jspecify.annotations.NullMarked;