From c78f4b290174163f29c32ff7d3d4e77854a62828 Mon Sep 17 00:00:00 2001 From: Exlll Date: Wed, 10 Aug 2022 10:55:20 +0200 Subject: [PATCH] Change TypeComponent and SerializerSelector to use AnnotatedType --- .../exlll/configlib/SerializerSelector.java | 50 ++++++++++++------- .../de/exlll/configlib/TypeComponent.java | 23 ++++----- .../configlib/SerializerSelectorTest.java | 6 +-- .../de/exlll/configlib/TypeComponentTest.java | 14 ++---- 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/configlib-core/src/main/java/de/exlll/configlib/SerializerSelector.java b/configlib-core/src/main/java/de/exlll/configlib/SerializerSelector.java index 67bd7ba..753a8fb 100644 --- a/configlib-core/src/main/java/de/exlll/configlib/SerializerSelector.java +++ b/configlib-core/src/main/java/de/exlll/configlib/SerializerSelector.java @@ -71,18 +71,21 @@ final class SerializerSelector { public Serializer select(TypeComponent component) { this.currentNesting = -1; this.serializeWith = component.annotation(SerializeWith.class); - return selectForType(component.genericType()); + return selectForType(component.annotatedType()); } - private Serializer selectForType(Type type) { + private Serializer selectForType(AnnotatedType annotatedType) { this.currentNesting++; - final Serializer custom = selectCustomSerializer(type); + + final Serializer custom = selectCustomSerializer(annotatedType); if (custom != null) return custom; - if (type instanceof Class cls) { - return selectForClass(cls); - } else if (type instanceof ParameterizedType pType) { - return selectForParameterizedType(pType); + + final Type type = annotatedType.getType(); + if (type instanceof Class) { + return selectForClass(annotatedType); + } else if (type instanceof ParameterizedType) { + return selectForParameterizedType((AnnotatedParameterizedType) annotatedType); } else if (type instanceof WildcardType) { String msg = baseExceptionMessage(type) + "Wildcard types cannot be serialized."; throw new ConfigurationException(msg); @@ -97,13 +100,19 @@ final class SerializerSelector { throw new ConfigurationException(baseExceptionMessage(type)); } - private Serializer selectCustomSerializer(Type type) { + private Serializer selectCustomSerializer(AnnotatedType annotatedType) { + // SerializeWith annotation if ((serializeWith != null) && (currentNesting == serializeWith.nesting())) return Reflect.callNoParamConstructor(serializeWith.serializer()); + + // Serializer registered for Type via configurations properties + final Type type = annotatedType.getType(); if (type instanceof Class cls) { if (properties.getSerializers().containsKey(cls)) return properties.getSerializers().get(cls); } + + // Serializer registered for condition via configurations properties for (var entry : properties.getSerializersByCondition().entrySet()) { if (entry.getKey().test(type)) return entry.getValue(); @@ -111,7 +120,8 @@ final class SerializerSelector { return null; } - private Serializer selectForClass(Class cls) { + private Serializer selectForClass(AnnotatedType annotatedType) { + final Class cls = (Class) annotatedType.getType(); if (DEFAULT_SERIALIZERS.containsKey(cls)) return DEFAULT_SERIALIZERS.get(cls); if (Reflect.isEnumType(cls)) { @@ -120,8 +130,9 @@ final class SerializerSelector { final var enumType = (Class>) cls; return new Serializers.EnumSerializer(enumType); } - if (Reflect.isArrayType(cls)) - return selectForArray(cls.getComponentType()); + if (Reflect.isArrayType(cls)) { + return selectForArray((AnnotatedArrayType) annotatedType); + } if (cls.isRecord()) { // The following cast won't fail because we just checked that it's a record. @SuppressWarnings("unchecked") @@ -137,7 +148,9 @@ final class SerializerSelector { throw new ConfigurationException(msg); } - private Serializer selectForArray(Class elementType) { + private Serializer selectForArray(AnnotatedArrayType annotatedType) { + final AnnotatedType annotatedElementType = annotatedType.getAnnotatedGenericComponentType(); + final Class elementType = (Class) annotatedElementType.getType(); if (elementType == boolean.class) { return new PrimitiveBooleanArraySerializer(); } else if (elementType == char.class) { @@ -155,16 +168,17 @@ final class SerializerSelector { } else if (elementType == double.class) { return new PrimitiveDoubleArraySerializer(); } - var elementSerializer = selectForType(elementType); + var elementSerializer = selectForType(annotatedElementType); var inputNulls = properties.inputNulls(); var outputNulls = properties.outputNulls(); return new ArraySerializer<>(elementType, elementSerializer, outputNulls, inputNulls); } - private Serializer selectForParameterizedType(ParameterizedType type) { + private Serializer selectForParameterizedType(AnnotatedParameterizedType annotatedType) { // the raw type returned by Java is always a class + final var type = (ParameterizedType) annotatedType.getType(); final var rawType = (Class) type.getRawType(); - final var typeArgs = type.getActualTypeArguments(); + final var typeArgs = annotatedType.getAnnotatedActualTypeArguments(); final var inputNulls = properties.inputNulls(); final var outputNulls = properties.outputNulls(); @@ -177,10 +191,10 @@ final class SerializerSelector { ? new SetAsListSerializer<>(elementSerializer, outputNulls, inputNulls) : new SetSerializer<>(elementSerializer, outputNulls, inputNulls); } else if (Reflect.isMapType(rawType)) { - if ((typeArgs[0] instanceof Class cls) && + if ((typeArgs[0].getType() instanceof Class cls) && (DEFAULT_SERIALIZERS.containsKey(cls) || Reflect.isEnumType(cls))) { - var keySerializer = selectForClass(cls); + var keySerializer = selectForClass(typeArgs[0]); var valSerializer = selectForType(typeArgs[1]); return new MapSerializer<>(keySerializer, valSerializer, outputNulls, inputNulls); } @@ -195,6 +209,6 @@ final class SerializerSelector { } private String baseExceptionMessage(Type type) { - return "Cannot select serializer for type '" + type + "'.\n"; + return "Cannot select serializer for type '%s'.\n".formatted(type); } } diff --git a/configlib-core/src/main/java/de/exlll/configlib/TypeComponent.java b/configlib-core/src/main/java/de/exlll/configlib/TypeComponent.java index c3f5d7a..298d363 100644 --- a/configlib-core/src/main/java/de/exlll/configlib/TypeComponent.java +++ b/configlib-core/src/main/java/de/exlll/configlib/TypeComponent.java @@ -1,10 +1,7 @@ package de.exlll.configlib; import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Field; -import java.lang.reflect.RecordComponent; -import java.lang.reflect.Type; +import java.lang.reflect.*; import static de.exlll.configlib.Validator.requireNonNull; @@ -37,11 +34,11 @@ sealed interface TypeComponent { Class type(); /** - * Returns the generic type of the component. + * Returns the annotated type of the component. * - * @return generic type of the component + * @return annotated type of component */ - Type genericType(); + AnnotatedType annotatedType(); /** * Returns the value the component is holding. @@ -89,8 +86,8 @@ sealed interface TypeComponent { } @Override - public Type genericType() { - return component.getGenericType(); + public AnnotatedType annotatedType() { + return component.getAnnotatedType(); } @Override @@ -116,13 +113,13 @@ sealed interface TypeComponent { } @Override - public Class type() { - return component.getType(); + public AnnotatedType annotatedType() { + return component.getAnnotatedType(); } @Override - public Type genericType() { - return component.getGenericType(); + public Class type() { + return component.getType(); } @Override diff --git a/configlib-core/src/test/java/de/exlll/configlib/SerializerSelectorTest.java b/configlib-core/src/test/java/de/exlll/configlib/SerializerSelectorTest.java index 013e018..c9e2833 100644 --- a/configlib-core/src/test/java/de/exlll/configlib/SerializerSelectorTest.java +++ b/configlib-core/src/test/java/de/exlll/configlib/SerializerSelectorTest.java @@ -370,7 +370,7 @@ class SerializerSelectorTest { () -> SELECTOR.select(component), ("Cannot select serializer for type '%s'.\n" + "Map keys can only be of simple or enum type.") - .formatted(component.genericType()) + .formatted(component.annotatedType().getType()) ); } @@ -384,7 +384,7 @@ class SerializerSelectorTest { () -> SELECTOR.select(component), ("Cannot select serializer for type '%s'.\n" + "Map keys can only be of simple or enum type.") - .formatted(component.genericType()) + .formatted(component.annotatedType().getType()) ); } @@ -399,7 +399,7 @@ class SerializerSelectorTest { () -> SELECTOR.select(component), ("Cannot select serializer for type '%s'.\n" + "Parameterized types other than lists, sets, and maps cannot be serialized.") - .formatted(component.genericType()) + .formatted(component.annotatedType().getType()) ); } diff --git a/configlib-core/src/test/java/de/exlll/configlib/TypeComponentTest.java b/configlib-core/src/test/java/de/exlll/configlib/TypeComponentTest.java index 16bfb0f..8680c2c 100644 --- a/configlib-core/src/test/java/de/exlll/configlib/TypeComponentTest.java +++ b/configlib-core/src/test/java/de/exlll/configlib/TypeComponentTest.java @@ -5,9 +5,7 @@ import de.exlll.configlib.TypeComponent.ConfigurationRecordComponent; import org.junit.jupiter.api.Test; import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.RecordComponent; -import java.lang.reflect.Type; import java.util.List; import java.util.Set; @@ -36,10 +34,8 @@ class TypeComponentTest { } @Test - void componentGenericType() { - ParameterizedType type = (ParameterizedType) COMPONENT.genericType(); - Type argument = type.getActualTypeArguments()[0]; - assertThat(argument, equalTo(String.class)); + void componentAnnotatedType() { + assertThat(COMPONENT.annotatedType(), equalTo(FIELD.getAnnotatedType())); } @Test @@ -76,10 +72,8 @@ class TypeComponentTest { } @Test - void componentGenericType() { - ParameterizedType type = (ParameterizedType) COMPONENT.genericType(); - Type argument = type.getActualTypeArguments()[0]; - assertThat(argument, equalTo(Integer.class)); + void componentAnnotatedType() { + assertThat(COMPONENT.annotatedType(), equalTo(RECORD_COMPONENT.getAnnotatedType())); } @Test