合成聚合注解支持处理多个根注解,并且可选择是否扫描根注解的元注解

This commit is contained in:
huangchengxing 2022-07-16 18:02:02 +08:00
parent d873b6e9da
commit c27c74f192
7 changed files with 176 additions and 77 deletions

View File

@ -1,5 +1,6 @@
package cn.hutool.core.annotation; package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.AnnotationScanner;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
@ -43,21 +44,32 @@ public abstract class AbstractAnnotationSynthesizer<T> implements AnnotationSynt
*/ */
protected final Collection<SynthesizedAnnotationPostProcessor> postProcessors; protected final Collection<SynthesizedAnnotationPostProcessor> postProcessors;
/**
* 注解扫描器
*/
protected final AnnotationScanner annotationScanner;
/** /**
* 构造一个注解合成器 * 构造一个注解合成器
* *
* @param source 当前查找的注解对象 * @param source 当前查找的注解对象
* @param annotationSelector 合成注解选择器 * @param annotationSelector 合成注解选择器
* @param annotationPostProcessors 注解后置处理器 * @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器该扫描器需要支持扫描注解类
*/ */
protected AbstractAnnotationSynthesizer( protected AbstractAnnotationSynthesizer(
T source, SynthesizedAnnotationSelector annotationSelector, Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors) { T source,
SynthesizedAnnotationSelector annotationSelector,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
Assert.notNull(source, "source must not null"); Assert.notNull(source, "source must not null");
Assert.notNull(annotationSelector, "annotationSelector must not null"); Assert.notNull(annotationSelector, "annotationSelector must not null");
Assert.notNull(annotationPostProcessors, "annotationPostProcessors must not null"); Assert.notNull(annotationPostProcessors, "annotationPostProcessors must not null");
Assert.notNull(annotationPostProcessors, "annotationScanner must not null");
this.source = source; this.source = source;
this.annotationSelector = annotationSelector; this.annotationSelector = annotationSelector;
this.annotationScanner = annotationScanner;
this.postProcessors = CollUtil.unmodifiable( this.postProcessors = CollUtil.unmodifiable(
CollUtil.sort(annotationPostProcessors, Comparator.comparing(SynthesizedAnnotationPostProcessor::order)) CollUtil.sort(annotationPostProcessors, Comparator.comparing(SynthesizedAnnotationPostProcessor::order))
); );

View File

@ -355,7 +355,7 @@ public class AnnotationUtil {
*/ */
public static <T extends Annotation> T getSynthesizedAnnotation(Annotation annotation, Class<T> annotationType) { public static <T extends Annotation> T getSynthesizedAnnotation(Annotation annotation, Class<T> annotationType) {
// TODO 缓存合成注解信息避免重复解析 // TODO 缓存合成注解信息避免重复解析
return SynthesizedAggregateAnnotation.from(annotation).synthesize(annotationType); return aggregatingFromAnnotationWithMeta(annotation).synthesize(annotationType);
} }
/** /**
@ -470,4 +470,24 @@ public class AnnotationUtil {
return method.getParameterCount() == 0 && method.getReturnType() != void.class; return method.getParameterCount() == 0 && method.getReturnType() != void.class;
} }
/**
* 对指定注解对象进行聚合
*
* @param annotation 注解对象
* @return 聚合注解
*/
static SynthesizedAggregateAnnotation aggregatingFromAnnotation(Annotation annotation) {
return new GenericSynthesizedAggregateAnnotation(Collections.singletonList(annotation), EmptyAnnotationScanner.INSTANCE);
}
/**
* 对指定注解对象及其元注解进行聚合
*
* @param annotation 注解对象
* @return 聚合注解
*/
static SynthesizedAggregateAnnotation aggregatingFromAnnotationWithMeta(Annotation annotation) {
return new GenericSynthesizedAggregateAnnotation(annotation);
}
} }

View File

@ -1,5 +1,6 @@
package cn.hutool.core.annotation; package cn.hutool.core.annotation;
import cn.hutool.core.annotation.scanner.AnnotationScanner;
import cn.hutool.core.annotation.scanner.MetaAnnotationScanner; import cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
@ -7,16 +8,14 @@ import cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.util.Arrays; import java.util.*;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/** /**
* {@link SynthesizedAggregateAnnotation}的基本实现表示一个根注解与根注解上的多层元注解的聚合得到的注解 * {@link SynthesizedAggregateAnnotation}的基本实现表示基于多个注解对象
* 或多个根注解对象与他们的多层元注解对象的聚合得到的注解
* *
* <p>假设现有注解AA上存在元注解BB上存在元注解C则对注解A进行解析 * <p>假设现有注解A若指定的{@link #annotationScanner}支持扫描注解A的元注解
* 将得到包含根注解A以及其元注解BC在内的合成元注解聚合{@link SynthesizedMetaAggregateAnnotation} * 且A上存在元注解BB上存在元注解C则对注解A进行解析将得到包含根注解A以及其元注解BC在内的合成元注解聚合{@link GenericSynthesizedAggregateAnnotation}
* {@link AnnotatedElement}的角度来说得到的合成注解是一个同时承载有ABC三个注解对象的被注解元素 * {@link AnnotatedElement}的角度来说得到的合成注解是一个同时承载有ABC三个注解对象的被注解元素
* 因此通过调用{@link AnnotatedElement}的相关方法将返回对应符合语义的注解对象 * 因此通过调用{@link AnnotatedElement}的相关方法将返回对应符合语义的注解对象
* *
@ -37,7 +36,7 @@ import java.util.Map;
* </ul> * </ul>
* 若用户需要自行扩展则需要保证上述三个处理器被正确注入当前实例 * 若用户需要自行扩展则需要保证上述三个处理器被正确注入当前实例
* *
* <p>{@link SynthesizedMetaAggregateAnnotation}支持通过{@link #getAttributeValue(String, Class)} * <p>{@link GenericSynthesizedAggregateAnnotation}支持通过{@link #getAttributeValue(String, Class)}
* 或通过{@link #synthesize(Class)}获得注解代理对象后获取指定类型的注解属性值 * 或通过{@link #synthesize(Class)}获得注解代理对象后获取指定类型的注解属性值
* 返回的属性值将根据合成注解中对应原始注解属性上的{@link Alias}{@link Link}注解而有所变化 * 返回的属性值将根据合成注解中对应原始注解属性上的{@link Alias}{@link Link}注解而有所变化
* 通过当前实例获取属性值时将经过{@link SynthesizedAnnotationAttributeProcessor}的处理<br> * 通过当前实例获取属性值时将经过{@link SynthesizedAnnotationAttributeProcessor}的处理<br>
@ -46,9 +45,16 @@ import java.util.Map;
* *
* @author huangchengxing * @author huangchengxing
* @see AnnotationUtil * @see AnnotationUtil
* @see SynthesizedAnnotationProxy
* @see SynthesizedAnnotationSelector * @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor
* @see AnnotationSynthesizer
* @see AnnotationScanner
*/ */
public class SynthesizedMetaAggregateAnnotation extends AbstractAnnotationSynthesizer<Annotation> implements SynthesizedAggregateAnnotation { public class GenericSynthesizedAggregateAnnotation
extends AbstractAnnotationSynthesizer<List<Annotation>>
implements SynthesizedAggregateAnnotation {
/** /**
* 根对象 * 根对象
@ -71,13 +77,25 @@ public class SynthesizedMetaAggregateAnnotation extends AbstractAnnotationSynthe
private final SynthesizedAnnotationAttributeProcessor attributeProcessor; private final SynthesizedAnnotationAttributeProcessor attributeProcessor;
/** /**
* 基于指定根注解为其层级结构中的全部注解构造一个合成注解 * 基于指定根注解为其与其元注解的层级结构中的全部注解构造一个合成注解
* 当层级结构中出现了相同的注解对象时将优先选择以距离根注解最近且优先被扫描的注解对象, * 当层级结构中出现了相同的注解对象时将优先选择以距离根注解最近且优先被扫描的注解对象,
* 当获取值时同样遵循该规则 * 当获取值时同样遵循该规则
* *
* @param source 源注解 * @param source 源注解
*/ */
public SynthesizedMetaAggregateAnnotation(Annotation source) { public GenericSynthesizedAggregateAnnotation(Annotation... source) {
this(Arrays.asList(source), new MetaAnnotationScanner());
}
/**
* 基于指定根注解为其层级结构中的全部注解构造一个合成注解
* 若扫描器支持对注解的层级结构进行扫描则若层级结构中出现了相同的注解对象时
* 将优先选择以距离根注解最近且优先被扫描的注解对象并且当获取注解属性值时同样遵循该规则
*
* @param source 源注解
* @param annotationScanner 注解扫描器该扫描器必须支持扫描注解类
*/
public GenericSynthesizedAggregateAnnotation(List<Annotation> source, AnnotationScanner annotationScanner) {
this( this(
source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY, source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY,
new CacheableSynthesizedAnnotationAttributeProcessor(), new CacheableSynthesizedAnnotationAttributeProcessor(),
@ -85,26 +103,29 @@ public class SynthesizedMetaAggregateAnnotation extends AbstractAnnotationSynthe
SynthesizedAnnotationPostProcessor.ALIAS_ANNOTATION_POST_PROCESSOR, SynthesizedAnnotationPostProcessor.ALIAS_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.MIRROR_LINK_ANNOTATION_POST_PROCESSOR, SynthesizedAnnotationPostProcessor.MIRROR_LINK_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.ALIAS_LINK_ANNOTATION_POST_PROCESSOR SynthesizedAnnotationPostProcessor.ALIAS_LINK_ANNOTATION_POST_PROCESSOR
) ),
annotationScanner
); );
} }
/** /**
* 基于指定根注解为其层级结构中的全部注解构造一个合成注解 * 基于指定根注解为其层级结构中的全部注解构造一个合成注解
* *
* @param annotation 当前查找的注解对象 * @param source 当前查找的注解对象
* @param annotationSelector 合成注解选择器 * @param annotationSelector 合成注解选择器
* @param attributeProcessor 注解属性处理器 * @param attributeProcessor 注解属性处理器
* @param annotationPostProcessors 注解后置处理器 * @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器该扫描器必须支持扫描注解类
*/ */
public SynthesizedMetaAggregateAnnotation( public GenericSynthesizedAggregateAnnotation(
Annotation annotation, List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector, SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor, SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors) { Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
this( this(
null, 0, 0, null, 0, 0,
annotation, annotationSelector, attributeProcessor, annotationPostProcessors source, annotationSelector, attributeProcessor, annotationPostProcessors, annotationScanner
); );
} }
@ -118,14 +139,16 @@ public class SynthesizedMetaAggregateAnnotation extends AbstractAnnotationSynthe
* @param annotationSelector 合成注解选择器 * @param annotationSelector 合成注解选择器
* @param attributeProcessor 注解属性处理器 * @param attributeProcessor 注解属性处理器
* @param annotationPostProcessors 注解后置处理器 * @param annotationPostProcessors 注解后置处理器
* @param annotationScanner 注解扫描器该扫描器必须支持扫描注解类
*/ */
SynthesizedMetaAggregateAnnotation( GenericSynthesizedAggregateAnnotation(
Object root, int verticalDistance, int horizontalDistance, Object root, int verticalDistance, int horizontalDistance,
Annotation source, List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector, SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor, SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors) { Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
super(source, annotationSelector, annotationPostProcessors); AnnotationScanner annotationScanner) {
super(source, annotationSelector, annotationPostProcessors, annotationScanner);
Assert.notNull(attributeProcessor, "attributeProcessor must not null"); Assert.notNull(attributeProcessor, "attributeProcessor must not null");
this.root = ObjectUtil.defaultIfNull(root, this); this.root = ObjectUtil.defaultIfNull(root, this);
@ -169,21 +192,31 @@ public class SynthesizedMetaAggregateAnnotation extends AbstractAnnotationSynthe
*/ */
@Override @Override
protected Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations() { protected Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations() {
Assert.isFalse(SynthesizedAnnotationProxy.isProxyAnnotation(source.getClass()), "source [{}] has been synthesized");
Map<Class<? extends Annotation>, SynthesizedAnnotation> annotationMap = new LinkedHashMap<>(); Map<Class<? extends Annotation>, SynthesizedAnnotation> annotationMap = new LinkedHashMap<>();
annotationMap.put(source.annotationType(), new MetaAnnotation(source, source, 0, 0));
new MetaAnnotationScanner().scan( // 根注解默认水平坐标为0根注解的元注解坐标从1开始
for (int i = 0; i < source.size(); i++) {
final Annotation sourceAnnotation = source.get(i);
Assert.isFalse(AnnotationUtil.isSynthesizedAnnotation(sourceAnnotation), "source [{}] has been synthesized");
annotationMap.put(sourceAnnotation.annotationType(), new MetaAnnotation(sourceAnnotation, sourceAnnotation, 0, i));
Assert.isTrue(
annotationScanner.support(sourceAnnotation.annotationType()),
"annotation scanner [{}] cannot support scan [{}]",
annotationScanner, sourceAnnotation.annotationType()
);
annotationScanner.scan(
(index, annotation) -> { (index, annotation) -> {
SynthesizedAnnotation oldAnnotation = annotationMap.get(annotation.annotationType()); SynthesizedAnnotation oldAnnotation = annotationMap.get(annotation.annotationType());
SynthesizedAnnotation newAnnotation = new MetaAnnotation(source, annotation, index, annotationMap.size()); SynthesizedAnnotation newAnnotation = new MetaAnnotation(sourceAnnotation, annotation, index + 1, annotationMap.size());
if (ObjectUtil.isNull(oldAnnotation)) { if (ObjectUtil.isNull(oldAnnotation)) {
annotationMap.put(annotation.annotationType(), newAnnotation); annotationMap.put(annotation.annotationType(), newAnnotation);
} else { } else {
annotationMap.put(annotation.annotationType(), annotationSelector.choose(oldAnnotation, newAnnotation)); annotationMap.put(annotation.annotationType(), annotationSelector.choose(oldAnnotation, newAnnotation));
} }
}, },
source.annotationType(), null sourceAnnotation.annotationType(), null
); );
}
return annotationMap; return annotationMap;
} }

View File

@ -33,7 +33,7 @@ import java.lang.annotation.Annotation;
* @see SynthesizedAnnotationSelector * @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor * @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor * @see SynthesizedAnnotationPostProcessor
* @see SynthesizedMetaAggregateAnnotation * @see GenericSynthesizedAggregateAnnotation
*/ */
public interface SynthesizedAggregateAnnotation extends AggregateAnnotation, Hierarchical, AnnotationSynthesizer, AnnotationAttributeValueProvider { public interface SynthesizedAggregateAnnotation extends AggregateAnnotation, Hierarchical, AnnotationSynthesizer, AnnotationAttributeValueProvider {
@ -99,15 +99,4 @@ public interface SynthesizedAggregateAnnotation extends AggregateAnnotation, Hie
@Override @Override
Object getAttributeValue(String attributeName, Class<?> attributeType); Object getAttributeValue(String attributeName, Class<?> attributeType);
/**
* 基于指定根注解构建包括其元注解在内的合成注解
*
* @param rootAnnotation 根注解
* @param <T> 注解类型
* @return 合成注解
*/
static <T extends Annotation> SynthesizedAggregateAnnotation from(T rootAnnotation) {
return new SynthesizedMetaAggregateAnnotation(rootAnnotation);
}
} }

View File

@ -33,18 +33,17 @@ public class SynthesizedAnnotationProxy implements InvocationHandler {
/** /**
* 创建一个代理注解生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类 * 创建一个代理注解生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类
* <ul>
* <li>当作为{@code annotationType}所指定的类型使用时其属性将通过合成它的{@link SynthesizedAggregateAnnotation}获取</li>
* <li>当作为{@link SyntheticProxyAnnotation}{@link SynthesizedAnnotation}使用时将可以获得原始注解实例的相关信息</li>
* </ul>
* *
* @param annotationType 注解类型 * @param annotationType 注解类型
* @param annotationAttributeValueProvider 注解属性值获取器 * @param annotationAttributeValueProvider 注解属性值获取器
* @param annotation 合成注解
* @return 代理注解 * @return 代理注解
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Annotation> T create( public static <T extends Annotation> T create(
Class<T> annotationType, AnnotationAttributeValueProvider annotationAttributeValueProvider, SynthesizedAnnotation annotation) { Class<T> annotationType,
AnnotationAttributeValueProvider annotationAttributeValueProvider,
SynthesizedAnnotation annotation) {
if (ObjectUtil.isNull(annotation)) { if (ObjectUtil.isNull(annotation)) {
return null; return null;
} }
@ -59,6 +58,18 @@ public class SynthesizedAnnotationProxy implements InvocationHandler {
); );
} }
/**
* 创建一个代理注解生成的代理对象将是{@link SyntheticProxyAnnotation}与指定的注解类的子类
*
* @param annotationType 注解类型
* @param annotation 合成注解
* @return 代理注解
*/
public static <T extends Annotation> T create(
Class<T> annotationType, SynthesizedAnnotation annotation) {
return create(annotationType, annotation, annotation);
}
/** /**
* 该类是否为通过{@link SynthesizedAnnotationProxy}生成的代理类 * 该类是否为通过{@link SynthesizedAnnotationProxy}生成的代理类
* *

View File

@ -0,0 +1,33 @@
package cn.hutool.core.annotation.scanner;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
* 默认不扫描任何元素的扫描器
*
* @author huangchengxing
*/
public class EmptyAnnotationScanner implements AnnotationScanner {
public static final EmptyAnnotationScanner INSTANCE = new EmptyAnnotationScanner();
@Override
public boolean support(AnnotatedElement annotatedEle) {
return true;
}
@Override
public List<Annotation> getAnnotations(AnnotatedElement annotatedEle) {
return Collections.emptyList();
}
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
// do nothing
}
}

View File

@ -10,13 +10,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
/** /**
* 合成注解{@link SynthesizedMetaAggregateAnnotation}的测试用例 * 合成注解{@link GenericSynthesizedAggregateAnnotation}的测试用例
* *
* @author huangchengxing * @author huangchengxing
*/ */
public class SyntheticMetaAnnotationTest { public class GenericSynthesizedAggregateAnnotationTest {
@Test @Test
public void baseSynthesisAnnotationWorkTest() { public void baseSynthesisAnnotationWorkTest() {
@ -25,10 +26,10 @@ public class SyntheticMetaAnnotationTest {
final GrandParentAnnotation grandParentAnnotation = ChildAnnotation.class.getAnnotation(GrandParentAnnotation.class); final GrandParentAnnotation grandParentAnnotation = ChildAnnotation.class.getAnnotation(GrandParentAnnotation.class);
final ParentAnnotation parentAnnotation = ChildAnnotation.class.getAnnotation(ParentAnnotation.class); final ParentAnnotation parentAnnotation = ChildAnnotation.class.getAnnotation(ParentAnnotation.class);
final ChildAnnotation childAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); final ChildAnnotation childAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class);
final SynthesizedMetaAggregateAnnotation syntheticMetaAnnotation = new SynthesizedMetaAggregateAnnotation(childAnnotation); final GenericSynthesizedAggregateAnnotation syntheticMetaAnnotation = new GenericSynthesizedAggregateAnnotation(childAnnotation);
// Annotation & AnnotatedElement // Annotation & AnnotatedElement
Assert.assertEquals(SynthesizedMetaAggregateAnnotation.class, syntheticMetaAnnotation.annotationType()); Assert.assertEquals(GenericSynthesizedAggregateAnnotation.class, syntheticMetaAnnotation.annotationType());
Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(GrandParentAnnotation.class)); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(GrandParentAnnotation.class));
Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ParentAnnotation.class)); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ParentAnnotation.class));
Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ChildAnnotation.class)); Assert.assertTrue(syntheticMetaAnnotation.isAnnotationPresent(ChildAnnotation.class));
@ -55,9 +56,9 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void synthesisAnnotationAttributeTest() { public void synthesisAnnotationAttributeTest() {
final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class);
SynthesizedMetaAggregateAnnotation syntheticMetaAnnotation = new SynthesizedMetaAggregateAnnotation(rootAnnotation); GenericSynthesizedAggregateAnnotation syntheticMetaAnnotation = new GenericSynthesizedAggregateAnnotation(rootAnnotation);
Assert.assertEquals(syntheticMetaAnnotation.getSource(), rootAnnotation); Assert.assertEquals(syntheticMetaAnnotation.getSource(), Collections.singletonList(rootAnnotation));
Assert.assertEquals(syntheticMetaAnnotation.annotationType(), SynthesizedMetaAggregateAnnotation.class); Assert.assertEquals(syntheticMetaAnnotation.annotationType(), GenericSynthesizedAggregateAnnotation.class);
Assert.assertEquals(3, syntheticMetaAnnotation.getAnnotations().length); Assert.assertEquals(3, syntheticMetaAnnotation.getAnnotations().length);
Assert.assertEquals("Child!", syntheticMetaAnnotation.getAttributeValue("childValue", String.class)); Assert.assertEquals("Child!", syntheticMetaAnnotation.getAttributeValue("childValue", String.class));
@ -69,7 +70,7 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void syntheticAnnotationTest() { public void syntheticAnnotationTest() {
final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class); final ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class);
SynthesizedMetaAggregateAnnotation syntheticMetaAnnotation = new SynthesizedMetaAggregateAnnotation(rootAnnotation); GenericSynthesizedAggregateAnnotation syntheticMetaAnnotation = new GenericSynthesizedAggregateAnnotation(rootAnnotation);
final ChildAnnotation childAnnotation = syntheticMetaAnnotation.synthesize(ChildAnnotation.class); final ChildAnnotation childAnnotation = syntheticMetaAnnotation.synthesize(ChildAnnotation.class);
SynthesizedAnnotation childSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ChildAnnotation.class); SynthesizedAnnotation childSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ChildAnnotation.class);
@ -82,7 +83,7 @@ public class SyntheticMetaAnnotationTest {
Assert.assertEquals("Child!", childAnnotation.childValue()); Assert.assertEquals("Child!", childAnnotation.childValue());
Assert.assertEquals("Child!", childAnnotation.childValueAlias()); Assert.assertEquals("Child!", childAnnotation.childValueAlias());
Assert.assertEquals(childAnnotation.grandParentType(), Integer.class); Assert.assertEquals(childAnnotation.grandParentType(), Integer.class);
Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAggregateAnnotation(childAnnotation)); Assert.assertThrows(IllegalArgumentException.class, () -> new GenericSynthesizedAggregateAnnotation(childAnnotation));
final ParentAnnotation parentAnnotation = syntheticMetaAnnotation.synthesize(ParentAnnotation.class); final ParentAnnotation parentAnnotation = syntheticMetaAnnotation.synthesize(ParentAnnotation.class);
SynthesizedAnnotation parentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ParentAnnotation.class); SynthesizedAnnotation parentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(ParentAnnotation.class);
@ -93,7 +94,7 @@ public class SyntheticMetaAnnotationTest {
Assert.assertNotNull(parentAnnotation); Assert.assertNotNull(parentAnnotation);
Assert.assertEquals("Child's Parent!", parentAnnotation.parentValue()); Assert.assertEquals("Child's Parent!", parentAnnotation.parentValue());
Assert.assertEquals("java.lang.Void", parentAnnotation.grandParentType()); Assert.assertEquals("java.lang.Void", parentAnnotation.grandParentType());
Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAggregateAnnotation(parentAnnotation)); Assert.assertThrows(IllegalArgumentException.class, () -> new GenericSynthesizedAggregateAnnotation(parentAnnotation));
final GrandParentAnnotation grandParentAnnotation = syntheticMetaAnnotation.synthesize(GrandParentAnnotation.class); final GrandParentAnnotation grandParentAnnotation = syntheticMetaAnnotation.synthesize(GrandParentAnnotation.class);
SynthesizedAnnotation grandParentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(GrandParentAnnotation.class); SynthesizedAnnotation grandParentSyntheticAnnotation = syntheticMetaAnnotation.getSynthesizedAnnotation(GrandParentAnnotation.class);
@ -105,13 +106,13 @@ public class SyntheticMetaAnnotationTest {
Assert.assertNotNull(grandParentAnnotation); Assert.assertNotNull(grandParentAnnotation);
Assert.assertEquals("Child's GrandParent!", grandParentAnnotation.grandParentValue()); Assert.assertEquals("Child's GrandParent!", grandParentAnnotation.grandParentValue());
Assert.assertEquals(grandParentAnnotation.grandParentType(), Integer.class); Assert.assertEquals(grandParentAnnotation.grandParentType(), Integer.class);
Assert.assertThrows(IllegalArgumentException.class, () -> new SynthesizedMetaAggregateAnnotation(grandParentAnnotation)); Assert.assertThrows(IllegalArgumentException.class, () -> new GenericSynthesizedAggregateAnnotation(grandParentAnnotation));
} }
@Test @Test
public void linkTest() { public void linkTest() {
final Method method = ReflectUtil.getMethod(AnnotationForLinkTest.class, "value"); final Method method = ReflectUtil.getMethod(AnnotationForLinkTest.class, "value");
final SynthesizedAggregateAnnotation synthesizedAnnotationAggregator = new SynthesizedMetaAggregateAnnotation(method.getAnnotation(AliasFor.class)); final SynthesizedAggregateAnnotation synthesizedAnnotationAggregator = new GenericSynthesizedAggregateAnnotation(method.getAnnotation(AliasFor.class));
final Link link = synthesizedAnnotationAggregator.synthesize(Link.class); final Link link = synthesizedAnnotationAggregator.synthesize(Link.class);
Assert.assertEquals(AnnotationForLinkTest.class, link.annotation()); Assert.assertEquals(AnnotationForLinkTest.class, link.annotation());
Assert.assertEquals("name", link.attribute()); Assert.assertEquals("name", link.attribute());
@ -120,19 +121,19 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void mirrorAttributeTest() { public void mirrorAttributeTest() {
AnnotationForMirrorTest annotation = ClassForMirrorTest.class.getAnnotation(AnnotationForMirrorTest.class); AnnotationForMirrorTest annotation = ClassForMirrorTest.class.getAnnotation(AnnotationForMirrorTest.class);
SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
AnnotationForMirrorTest syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); AnnotationForMirrorTest syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class);
Assert.assertEquals("Foo", syntheticAnnotation.name()); Assert.assertEquals("Foo", syntheticAnnotation.name());
Assert.assertEquals("Foo", syntheticAnnotation.value()); Assert.assertEquals("Foo", syntheticAnnotation.value());
annotation = ClassForMirrorTest2.class.getAnnotation(AnnotationForMirrorTest.class); annotation = ClassForMirrorTest2.class.getAnnotation(AnnotationForMirrorTest.class);
synthetic = new SynthesizedMetaAggregateAnnotation(annotation); synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class);
Assert.assertEquals("Foo", syntheticAnnotation.name()); Assert.assertEquals("Foo", syntheticAnnotation.name());
Assert.assertEquals("Foo", syntheticAnnotation.value()); Assert.assertEquals("Foo", syntheticAnnotation.value());
annotation = ClassForMirrorTest3.class.getAnnotation(AnnotationForMirrorTest.class); annotation = ClassForMirrorTest3.class.getAnnotation(AnnotationForMirrorTest.class);
synthetic = new SynthesizedMetaAggregateAnnotation(annotation); synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class); syntheticAnnotation = synthetic.synthesize(AnnotationForMirrorTest.class);
AnnotationForMirrorTest finalSyntheticAnnotation = syntheticAnnotation; AnnotationForMirrorTest finalSyntheticAnnotation = syntheticAnnotation;
Assert.assertThrows(IllegalArgumentException.class, finalSyntheticAnnotation::name); Assert.assertThrows(IllegalArgumentException.class, finalSyntheticAnnotation::name);
@ -141,14 +142,14 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void aliasForTest() { public void aliasForTest() {
AnnotationForAliasForTest annotation = ClassForAliasForTest.class.getAnnotation(AnnotationForAliasForTest.class); AnnotationForAliasForTest annotation = ClassForAliasForTest.class.getAnnotation(AnnotationForAliasForTest.class);
SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
MetaAnnotationForAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class); MetaAnnotationForAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class);
Assert.assertEquals("Meta", metaAnnotation.name()); Assert.assertEquals("Meta", metaAnnotation.name());
AnnotationForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class); AnnotationForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class);
Assert.assertEquals("", childAnnotation.value()); Assert.assertEquals("", childAnnotation.value());
annotation = ClassForAliasForTest2.class.getAnnotation(AnnotationForAliasForTest.class); annotation = ClassForAliasForTest2.class.getAnnotation(AnnotationForAliasForTest.class);
synthetic = new SynthesizedMetaAggregateAnnotation(annotation); synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class); metaAnnotation = synthetic.synthesize(MetaAnnotationForAliasForTest.class);
Assert.assertEquals("Foo", metaAnnotation.name()); Assert.assertEquals("Foo", metaAnnotation.name());
childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class); childAnnotation = synthetic.synthesize(AnnotationForAliasForTest.class);
@ -158,14 +159,14 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void forceAliasForTest() { public void forceAliasForTest() {
AnnotationForceForAliasForTest annotation = ClassForForceAliasForTest.class.getAnnotation(AnnotationForceForAliasForTest.class); AnnotationForceForAliasForTest annotation = ClassForForceAliasForTest.class.getAnnotation(AnnotationForceForAliasForTest.class);
SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
MetaAnnotationForForceAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class); MetaAnnotationForForceAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class);
Assert.assertEquals("", metaAnnotation.name()); Assert.assertEquals("", metaAnnotation.name());
AnnotationForceForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class); AnnotationForceForAliasForTest childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class);
Assert.assertEquals("", childAnnotation.value()); Assert.assertEquals("", childAnnotation.value());
annotation = ClassForForceAliasForTest2.class.getAnnotation(AnnotationForceForAliasForTest.class); annotation = ClassForForceAliasForTest2.class.getAnnotation(AnnotationForceForAliasForTest.class);
synthetic = new SynthesizedMetaAggregateAnnotation(annotation); synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class); metaAnnotation = synthetic.synthesize(MetaAnnotationForForceAliasForTest.class);
Assert.assertEquals("Foo", metaAnnotation.name()); Assert.assertEquals("Foo", metaAnnotation.name());
childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class); childAnnotation = synthetic.synthesize(AnnotationForceForAliasForTest.class);
@ -175,7 +176,7 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void aliasForAndMirrorTest() { public void aliasForAndMirrorTest() {
AnnotationForMirrorThenAliasForTest annotation = ClassForAliasForAndMirrorTest.class.getAnnotation(AnnotationForMirrorThenAliasForTest.class); AnnotationForMirrorThenAliasForTest annotation = ClassForAliasForAndMirrorTest.class.getAnnotation(AnnotationForMirrorThenAliasForTest.class);
SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
MetaAnnotationForMirrorThenAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForMirrorThenAliasForTest.class); MetaAnnotationForMirrorThenAliasForTest metaAnnotation = synthetic.synthesize(MetaAnnotationForMirrorThenAliasForTest.class);
Assert.assertEquals("test", metaAnnotation.name()); Assert.assertEquals("test", metaAnnotation.name());
Assert.assertEquals("test", metaAnnotation.value()); Assert.assertEquals("test", metaAnnotation.value());
@ -186,7 +187,7 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void multiAliasForTest() { public void multiAliasForTest() {
final AnnotationForMultiAliasForTest annotation = ClassForMultiAliasForTest.class.getAnnotation(AnnotationForMultiAliasForTest.class); final AnnotationForMultiAliasForTest annotation = ClassForMultiAliasForTest.class.getAnnotation(AnnotationForMultiAliasForTest.class);
final SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); final SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
final MetaAnnotationForMultiAliasForTest1 metaAnnotation1 = synthetic.synthesize(MetaAnnotationForMultiAliasForTest1.class); final MetaAnnotationForMultiAliasForTest1 metaAnnotation1 = synthetic.synthesize(MetaAnnotationForMultiAliasForTest1.class);
Assert.assertEquals("test", metaAnnotation1.name()); Assert.assertEquals("test", metaAnnotation1.name());
@ -200,7 +201,7 @@ public class SyntheticMetaAnnotationTest {
@Test @Test
public void implicitAliasTest() { public void implicitAliasTest() {
final AnnotationForImplicitAliasTest annotation = ClassForImplicitAliasTest.class.getAnnotation(AnnotationForImplicitAliasTest.class); final AnnotationForImplicitAliasTest annotation = ClassForImplicitAliasTest.class.getAnnotation(AnnotationForImplicitAliasTest.class);
final SynthesizedAggregateAnnotation synthetic = new SynthesizedMetaAggregateAnnotation(annotation); final SynthesizedAggregateAnnotation synthetic = new GenericSynthesizedAggregateAnnotation(annotation);
final MetaAnnotationForImplicitAliasTest metaAnnotation = synthetic.synthesize(MetaAnnotationForImplicitAliasTest.class); final MetaAnnotationForImplicitAliasTest metaAnnotation = synthetic.synthesize(MetaAnnotationForImplicitAliasTest.class);
Assert.assertEquals("Meta", metaAnnotation.name()); Assert.assertEquals("Meta", metaAnnotation.name());