mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
支持处理可重复注解
This commit is contained in:
@@ -243,6 +243,25 @@ public class AnnotatedElementUtilTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllAnnotations() {
|
||||
Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation3.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation3s.length);
|
||||
Assert.assertEquals(ANNOTATION3, resolvedAnnotation3s[0]); // value与alias互为别名
|
||||
|
||||
Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation2.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation2s.length);
|
||||
Assert.assertEquals(ANNOTATION2, resolvedAnnotation2s[0]); // value与alias互为别名
|
||||
|
||||
Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation1.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation1s.length);
|
||||
Assert.assertEquals(ANNOTATION1, resolvedAnnotation1s[0]);
|
||||
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation4.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation5.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllAnnotations(Foo.class, Annotation6.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResolvedAnnotation() {
|
||||
Annotation3 resolvedAnnotation3 = AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation3.class);
|
||||
@@ -264,6 +283,33 @@ public class AnnotatedElementUtilTest {
|
||||
Assert.assertNull(AnnotatedElementUtil.getResolvedAnnotation(Foo.class, Annotation6.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllResolvedAnnotations() {
|
||||
Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation3.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation3s.length);
|
||||
Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0];
|
||||
Assert.assertNotNull(resolvedAnnotation3);
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value());
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名
|
||||
|
||||
Annotation2[] resolvedAnnotation2s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation2.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation2s.length);
|
||||
Annotation2 resolvedAnnotation2 = resolvedAnnotation2s[0];
|
||||
Assert.assertNotNull(resolvedAnnotation2);
|
||||
Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖
|
||||
|
||||
Annotation1[] resolvedAnnotation1s = AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation1.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation1s.length);
|
||||
Annotation1 resolvedAnnotation1 = resolvedAnnotation1s[0];
|
||||
Assert.assertNotNull(resolvedAnnotation1);
|
||||
Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖
|
||||
Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名
|
||||
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation4.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation5.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllResolvedAnnotations(Foo.class, Annotation6.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResolvedAnnotations() {
|
||||
Map<Class<?>, Annotation> annotationMap = Stream.of(AnnotatedElementUtil.getResolvedAnnotations(Foo.class))
|
||||
@@ -299,6 +345,20 @@ public class AnnotatedElementUtilTest {
|
||||
Assert.assertNull(AnnotatedElementUtil.getDirectlyAnnotation(Foo.class, Annotation6.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllDirectlyAnnotations() {
|
||||
Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyAnnotations(Foo.class, Annotation3.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation3s.length);
|
||||
Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0];
|
||||
Assert.assertEquals(ANNOTATION3, resolvedAnnotation3);
|
||||
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation2.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation1.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation4.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation5.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation6.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDirectlyAnnotations() {
|
||||
Annotation[] annotations = AnnotatedElementUtil.getDirectlyAnnotations(Foo.class);
|
||||
@@ -320,6 +380,22 @@ public class AnnotatedElementUtilTest {
|
||||
Assert.assertNull(AnnotatedElementUtil.getDirectlyResolvedAnnotation(Foo.class, Annotation6.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDirectlyAllResolvedAnnotations() {
|
||||
Annotation3[] resolvedAnnotation3s = AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation3.class);
|
||||
Assert.assertEquals(1, resolvedAnnotation3s.length);
|
||||
Annotation3 resolvedAnnotation3 = resolvedAnnotation3s[0];
|
||||
Assert.assertNotNull(resolvedAnnotation3);
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value());
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名
|
||||
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation2.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation1.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation4.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation5.class).length);
|
||||
Assert.assertEquals(0, AnnotatedElementUtil.getAllDirectlyResolvedAnnotations(Foo.class, Annotation6.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDirectlyResolvedAnnotations() {
|
||||
Annotation[] annotations = AnnotatedElementUtil.getDirectlyResolvedAnnotations(Foo.class);
|
||||
@@ -364,6 +440,39 @@ public class AnnotatedElementUtilTest {
|
||||
Assert.assertEquals(ANNOTATION5, resolvedElement.getAnnotation(Annotation5.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHierarchyRepeatableMetaElement() {
|
||||
Assert.assertNotNull(AnnotatedElementUtil.toHierarchyRepeatableMetaElement(null, false));
|
||||
Assert.assertNotNull(AnnotatedElementUtil.toHierarchyRepeatableMetaElement(null, true));
|
||||
AnnotatedElement element = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, false);
|
||||
|
||||
// 带有元注解
|
||||
Assert.assertArrayEquals(ANNOTATIONS, element.getAnnotations());
|
||||
|
||||
// 不带元注解
|
||||
Assert.assertArrayEquals(DECLARED_ANNOTATIONS, element.getDeclaredAnnotations());
|
||||
|
||||
// 解析注解属性
|
||||
AnnotatedElement resolvedElement = AnnotatedElementUtil.toHierarchyRepeatableMetaElement(Foo.class, true);
|
||||
Annotation3 resolvedAnnotation3 = resolvedElement.getAnnotation(Annotation3.class);
|
||||
Assert.assertNotNull(resolvedAnnotation3);
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value());
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名
|
||||
|
||||
Annotation2 resolvedAnnotation2 = resolvedElement.getAnnotation(Annotation2.class);
|
||||
Assert.assertNotNull(resolvedAnnotation2);
|
||||
Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖
|
||||
|
||||
Annotation1 resolvedAnnotation1 = resolvedElement.getAnnotation(Annotation1.class);
|
||||
Assert.assertNotNull(resolvedAnnotation1);
|
||||
Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖
|
||||
Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名
|
||||
|
||||
Assert.assertEquals(ANNOTATION4, resolvedElement.getAnnotation(Annotation4.class));
|
||||
Assert.assertEquals(ANNOTATION6, resolvedElement.getAnnotation(Annotation6.class));
|
||||
Assert.assertEquals(ANNOTATION5, resolvedElement.getAnnotation(Annotation5.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHierarchyElement() {
|
||||
Assert.assertNotNull(AnnotatedElementUtil.toHierarchyElement(Foo.class));
|
||||
@@ -401,6 +510,36 @@ public class AnnotatedElementUtilTest {
|
||||
Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToRepeatableMetaElement() {
|
||||
Assert.assertNotNull(AnnotatedElementUtil.toRepeatableMetaElement(null, RepeatableAnnotationCollector.none(), false));
|
||||
Assert.assertNotNull(AnnotatedElementUtil.toRepeatableMetaElement(null, RepeatableAnnotationCollector.none(), true));
|
||||
|
||||
// 不解析注解属性
|
||||
AnnotatedElement element = AnnotatedElementUtil.toRepeatableMetaElement(Foo.class, RepeatableAnnotationCollector.none(), false);
|
||||
Assert.assertEquals(element, AnnotatedElementUtil.toRepeatableMetaElement(Foo.class, RepeatableAnnotationCollector.none(), false)); // 第二次获取时从缓存中获取
|
||||
Assert.assertArrayEquals(new Annotation[]{ANNOTATION3, ANNOTATION2, ANNOTATION1}, element.getAnnotations());
|
||||
|
||||
// 解析注解属性
|
||||
element = AnnotatedElementUtil.toRepeatableMetaElement(Foo.class, RepeatableAnnotationCollector.none(), true);
|
||||
Assert.assertEquals(element, AnnotatedElementUtil.toRepeatableMetaElement(Foo.class, RepeatableAnnotationCollector.none(), true)); // 第二次获取时从缓存中获取
|
||||
Assert.assertEquals(3, element.getAnnotations().length);
|
||||
|
||||
Annotation3 resolvedAnnotation3 = element.getAnnotation(Annotation3.class);
|
||||
Assert.assertNotNull(resolvedAnnotation3);
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), ANNOTATION3.value());
|
||||
Assert.assertEquals(resolvedAnnotation3.alias(), resolvedAnnotation3.value()); // value与alias互为别名
|
||||
|
||||
Annotation2 resolvedAnnotation2 = element.getAnnotation(Annotation2.class);
|
||||
Assert.assertNotNull(resolvedAnnotation2);
|
||||
Assert.assertEquals(resolvedAnnotation2.num(), ANNOTATION3.num()); // num属性被Annotation3.num覆盖
|
||||
|
||||
Annotation1 resolvedAnnotation1 = element.getAnnotation(Annotation1.class);
|
||||
Assert.assertNotNull(resolvedAnnotation1);
|
||||
Assert.assertEquals(ANNOTATION3.value(), resolvedAnnotation1.value()); // value属性被Annotation3.value覆盖
|
||||
Assert.assertEquals(resolvedAnnotation1.value(), resolvedAnnotation1.alias()); // value与alias互为别名
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsElement() {
|
||||
Annotation[] annotations = new Annotation[]{ANNOTATION1, ANNOTATION2};
|
||||
@@ -474,6 +613,22 @@ public class AnnotatedElementUtilTest {
|
||||
int num() default Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Foo.class上注解情况如下:
|
||||
* <pre>{@code
|
||||
* annotation3 => annotation2 => annotation1
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Super.class上注解情况如下:
|
||||
* <pre>{@code
|
||||
* annotation4
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Interface.class上注解情况如下:
|
||||
* <pre>{@code
|
||||
* annotation6 => annotation5 => annotation6【循环引用】
|
||||
* }</pre>
|
||||
*/
|
||||
@Annotation3(value = "foo", num = Integer.MAX_VALUE)
|
||||
private static class Foo extends Super implements Interface {}
|
||||
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -12,6 +14,13 @@ import java.util.Map;
|
||||
*/
|
||||
public class AnnotationUtilTest {
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotations() {
|
||||
Annotation[] annotations = AnnotationUtil.getDeclaredAnnotations(ClassForTest.class);
|
||||
Assert.assertArrayEquals(annotations, ClassForTest.class.getDeclaredAnnotations());
|
||||
Assert.assertSame(annotations, AnnotationUtil.getDeclaredAnnotations(ClassForTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToCombination() {
|
||||
final CombinationAnnotationElement element = AnnotationUtil.toCombination(ClassForTest.class);
|
||||
@@ -115,6 +124,21 @@ public class AnnotationUtilTest {
|
||||
Assert.assertEquals(MetaAnnotationForTest.class, annotation.annotationType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotationAttributes() {
|
||||
Method[] methods = AnnotationUtil.getAnnotationAttributes(AnnotationForTest.class);
|
||||
Assert.assertSame(methods, AnnotationUtil.getAnnotationAttributes(AnnotationForTest.class));
|
||||
Assert.assertEquals(1, methods.length);
|
||||
Assert.assertArrayEquals(AnnotationForTest.class.getDeclaredMethods(), methods);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
public void testIsAnnotationAttribute() {
|
||||
Assert.assertFalse(AnnotationUtil.isAnnotationAttribute(AnnotationForTest.class.getMethod("equals", Object.class)));
|
||||
Assert.assertTrue(AnnotationUtil.isAnnotationAttribute(AnnotationForTest.class.getMethod("value")));
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface MetaAnnotationForTest{
|
||||
|
@@ -111,6 +111,7 @@ public class MetaAnnotatedElementTest {
|
||||
new Annotation[]{ annotation4 },
|
||||
element.getAnnotationsByType(Annotation4.class)
|
||||
);
|
||||
Assert.assertEquals(0, element.getAnnotationsByType(None.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,6 +122,7 @@ public class MetaAnnotatedElementTest {
|
||||
new Annotation[]{ annotation4 },
|
||||
element.getDeclaredAnnotationsByType(Annotation4.class)
|
||||
);
|
||||
Assert.assertEquals(0, element.getDeclaredAnnotationsByType(None.class).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -168,6 +170,11 @@ public class MetaAnnotatedElementTest {
|
||||
Assert.assertSame(source, element.getElement());
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface None { }
|
||||
|
||||
@Annotation4 // 循环引用
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation1 {
|
||||
|
@@ -0,0 +1,220 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* test for {@link RepeatableAnnotationCollector}
|
||||
*
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class RepeatableAnnotationCollectorTest {
|
||||
|
||||
private static final Annotation1 ANNOTATION1 = Foo.class.getAnnotation(Annotation1.class);
|
||||
private static final List<Annotation2> ANNOTATION2S = Arrays.asList(ANNOTATION1.value());
|
||||
private static final List<Annotation3> ANNOTATION3S = ANNOTATION2S.stream()
|
||||
.map(Annotation2::value)
|
||||
.flatMap(Stream::of)
|
||||
.collect(Collectors.toList());
|
||||
private static final List<Annotation> ANNOTATIONS = new ArrayList<>();
|
||||
static {
|
||||
ANNOTATIONS.add(ANNOTATION1);
|
||||
ANNOTATIONS.addAll(ANNOTATION2S);
|
||||
ANNOTATIONS.addAll(ANNOTATION3S);
|
||||
}
|
||||
|
||||
private static final BiPredicate<Annotation, Method> PREDICATE = (annotation, attribute) -> {
|
||||
// 属性名需为“value”
|
||||
if (!CharSequenceUtil.equals("value", attribute.getName())) {
|
||||
return false;
|
||||
}
|
||||
final Class<?> attributeType = attribute.getReturnType();
|
||||
// 返回值类型需为数组
|
||||
return attributeType.isArray()
|
||||
// 且数组元素需为注解
|
||||
&& attributeType.getComponentType()
|
||||
.isAnnotation()
|
||||
// 该注解类必须被@Repeatable注解,但不要求与当前属性的声明方法一致
|
||||
&& attributeType.getComponentType()
|
||||
.isAnnotationPresent(Repeatable.class);
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testNone() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.none());
|
||||
|
||||
Assert.assertEquals(0, collector.getRepeatableAnnotations(null).size());
|
||||
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation), collector.getRepeatableAnnotations(annotation));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3));
|
||||
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, Annotation3.class));
|
||||
Assert.assertTrue(collector.getRepeatableAnnotations(annotation3, Annotation1.class).isEmpty());
|
||||
Assert.assertTrue(collector.getRepeatableAnnotations(null, Annotation1.class).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoneWhenAccumulate() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.none();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.none());
|
||||
|
||||
Assert.assertEquals(0, collector.getRepeatableAnnotations(null, true).size());
|
||||
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation), collector.getRepeatableAnnotations(annotation, true));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericCollector() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.standard());
|
||||
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
List<Annotation3> annotations = Stream.of(annotation.value())
|
||||
.map(Annotation2::value)
|
||||
.flatMap(Stream::of)
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertEquals(annotations, collector.getRepeatableAnnotations(annotation));
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3));
|
||||
|
||||
Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class));
|
||||
Assert.assertEquals(ANNOTATION2S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation2.class));
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation3.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericCollectorWhenAccumulate() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.standard();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.standard());
|
||||
|
||||
List<Annotation> annotations = new ArrayList<>();
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
annotations.add(annotation);
|
||||
annotations.addAll(Arrays.asList(annotation.value()));
|
||||
Stream.of(annotation.value())
|
||||
.map(Annotation2::value)
|
||||
.flatMap(Stream::of)
|
||||
.forEach(annotations::add);
|
||||
Assert.assertEquals(annotations, collector.getRepeatableAnnotations(annotation, true));
|
||||
|
||||
Assert.assertEquals(ANNOTATIONS, collector.getRepeatableAnnotations(ANNOTATION1, true));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionCollector() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE);
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
List<Annotation3> annotations = Stream.of(annotation.value())
|
||||
.map(Annotation2::value)
|
||||
.flatMap(Stream::of)
|
||||
.collect(Collectors.toList());
|
||||
Assert.assertEquals(annotations, collector.getRepeatableAnnotations(annotation));
|
||||
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3));
|
||||
|
||||
Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class));
|
||||
Assert.assertEquals(ANNOTATION2S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation2.class));
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation3.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionCollectorWhenAccumulate() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.condition(PREDICATE);
|
||||
|
||||
List<Annotation> annotations = new ArrayList<>();
|
||||
Annotation1 annotation = Foo.class.getAnnotation(Annotation1.class);
|
||||
annotations.add(annotation);
|
||||
annotations.addAll(Arrays.asList(annotation.value()));
|
||||
Stream.of(annotation.value())
|
||||
.map(Annotation2::value)
|
||||
.flatMap(Stream::of)
|
||||
.forEach(annotations::add);
|
||||
Assert.assertEquals(annotations, collector.getRepeatableAnnotations(annotation, true));
|
||||
Assert.assertEquals(ANNOTATIONS, collector.getRepeatableAnnotations(ANNOTATION1, true));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullCollector() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.full());
|
||||
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3));
|
||||
|
||||
Assert.assertEquals(Collections.singletonList(ANNOTATION1), collector.getRepeatableAnnotations(ANNOTATION1, Annotation1.class));
|
||||
Assert.assertEquals(ANNOTATION2S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation2.class));
|
||||
Assert.assertEquals(ANNOTATION3S, collector.getRepeatableAnnotations(ANNOTATION1, Annotation3.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFullCollectorWhenAccumulate() {
|
||||
RepeatableAnnotationCollector collector = RepeatableAnnotationCollector.full();
|
||||
Assert.assertSame(collector, RepeatableAnnotationCollector.full());
|
||||
|
||||
Assert.assertEquals(ANNOTATIONS, collector.getRepeatableAnnotations(ANNOTATION1, true));
|
||||
|
||||
Annotation3 annotation3 = Foo.class.getAnnotation(Annotation3.class);
|
||||
Assert.assertEquals(Collections.singletonList(annotation3), collector.getRepeatableAnnotations(annotation3, true));
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation1 {
|
||||
Annotation2[] value() default {};
|
||||
}
|
||||
|
||||
@Repeatable(Annotation1.class)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation2 {
|
||||
Annotation3[] value() default {};
|
||||
}
|
||||
|
||||
@Repeatable(Annotation2.class)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation3 {
|
||||
int value();
|
||||
String name() default "";
|
||||
}
|
||||
|
||||
@Annotation3(Integer.MIN_VALUE)
|
||||
@Annotation1({
|
||||
@Annotation2({@Annotation3(1), @Annotation3(2)}),
|
||||
@Annotation2({@Annotation3(3), @Annotation3(4)})
|
||||
})
|
||||
private static class Foo {}
|
||||
|
||||
}
|
@@ -0,0 +1,212 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import cn.hutool.core.collection.iter.IterUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* test for {@link RepeatableMetaAnnotatedElement}
|
||||
*
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class RepeatableMetaAnnotatedElementTest {
|
||||
|
||||
private static final BiFunction<ResolvedAnnotationMapping, Annotation, ResolvedAnnotationMapping> RESOLVED_MAPPING_FACTORY =
|
||||
(source, annotation) -> new ResolvedAnnotationMapping(source, annotation, true);
|
||||
|
||||
private static final BiFunction<ResolvedAnnotationMapping, Annotation, ResolvedAnnotationMapping> MAPPING_FACTORY =
|
||||
(source, annotation) -> new ResolvedAnnotationMapping(source, annotation, false);
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY);
|
||||
Assert.assertEquals(element, element);
|
||||
Assert.assertNotEquals(element, null);
|
||||
Assert.assertEquals(element, RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY));
|
||||
Assert.assertNotEquals(element, RepeatableMetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY));
|
||||
Assert.assertNotEquals(element, RepeatableMetaAnnotatedElement.create(Annotation1.class, MAPPING_FACTORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
int hashCode = RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode();
|
||||
Assert.assertEquals(hashCode, RepeatableMetaAnnotatedElement.create(Foo.class, RESOLVED_MAPPING_FACTORY).hashCode());
|
||||
Assert.assertNotEquals(hashCode, RepeatableMetaAnnotatedElement.create(Foo.class, MAPPING_FACTORY).hashCode());
|
||||
Assert.assertNotEquals(hashCode, RepeatableMetaAnnotatedElement.create(Annotation1.class, MAPPING_FACTORY).hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAnnotationPresent() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
Assert.assertTrue(element.isAnnotationPresent(Annotation1.class));
|
||||
Assert.assertTrue(element.isAnnotationPresent(Annotation2.class));
|
||||
Assert.assertTrue(element.isAnnotationPresent(Annotation3.class));
|
||||
Assert.assertTrue(element.isAnnotationPresent(Annotation4.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotations() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
List<Class<? extends Annotation>> annotationTypes = Arrays.stream(element.getAnnotations())
|
||||
.map(Annotation::annotationType)
|
||||
.collect(Collectors.toList());
|
||||
Map<Class<? extends Annotation>, Integer> countMap = IterUtil.countMap(annotationTypes.iterator());
|
||||
|
||||
Assert.assertEquals((Integer)1, countMap.get(Annotation1.class));
|
||||
Assert.assertEquals((Integer)2, countMap.get(Annotation2.class));
|
||||
Assert.assertEquals((Integer)4, countMap.get(Annotation3.class));
|
||||
Assert.assertEquals((Integer)7, countMap.get(Annotation4.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotation() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
|
||||
Annotation1 annotation1 = Foo.class.getAnnotation(Annotation1.class);
|
||||
Assert.assertEquals(annotation1, element.getAnnotation(Annotation1.class));
|
||||
|
||||
Annotation4 annotation4 = Annotation1.class.getAnnotation(Annotation4.class);
|
||||
Assert.assertEquals(annotation4, element.getAnnotation(Annotation4.class));
|
||||
|
||||
Annotation2 annotation2 = annotation1.value()[0];
|
||||
Assert.assertEquals(annotation2, element.getAnnotation(Annotation2.class));
|
||||
|
||||
Annotation3 annotation3 = annotation2.value()[0];
|
||||
Assert.assertEquals(annotation3, element.getAnnotation(Annotation3.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAnnotationsByType() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
|
||||
Annotation[] annotations = element.getAnnotationsByType(Annotation1.class);
|
||||
Assert.assertEquals(1, annotations.length);
|
||||
|
||||
annotations = element.getAnnotationsByType(Annotation2.class);
|
||||
Assert.assertEquals(2, annotations.length);
|
||||
|
||||
annotations = element.getAnnotationsByType(Annotation3.class);
|
||||
Assert.assertEquals(4, annotations.length);
|
||||
|
||||
annotations = element.getAnnotationsByType(Annotation4.class);
|
||||
Assert.assertEquals(7, annotations.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotations() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
List<Class<? extends Annotation>> annotationTypes = Arrays.stream(element.getDeclaredAnnotations())
|
||||
.map(Annotation::annotationType)
|
||||
.collect(Collectors.toList());
|
||||
Map<Class<? extends Annotation>, Integer> countMap = IterUtil.countMap(annotationTypes.iterator());
|
||||
|
||||
Assert.assertEquals((Integer)1, countMap.get(Annotation1.class));
|
||||
Assert.assertFalse(countMap.containsKey(Annotation2.class));
|
||||
Assert.assertFalse(countMap.containsKey(Annotation3.class));
|
||||
Assert.assertFalse(countMap.containsKey(Annotation4.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotation() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
|
||||
Annotation1 annotation1 = Foo.class.getDeclaredAnnotation(Annotation1.class);
|
||||
Assert.assertEquals(annotation1, element.getDeclaredAnnotation(Annotation1.class));
|
||||
Assert.assertNull(element.getDeclaredAnnotation(Annotation3.class));
|
||||
Assert.assertNull(element.getDeclaredAnnotation(Annotation4.class));
|
||||
Assert.assertNull(element.getDeclaredAnnotation(Annotation2.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDeclaredAnnotationsByType() {
|
||||
AnnotatedElement element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
|
||||
Annotation[] annotations = element.getDeclaredAnnotationsByType(Annotation1.class);
|
||||
Assert.assertEquals(1, annotations.length);
|
||||
|
||||
annotations = element.getDeclaredAnnotationsByType(Annotation2.class);
|
||||
Assert.assertEquals(0, annotations.length);
|
||||
|
||||
annotations = element.getDeclaredAnnotationsByType(Annotation3.class);
|
||||
Assert.assertEquals(0, annotations.length);
|
||||
|
||||
annotations = element.getDeclaredAnnotationsByType(Annotation4.class);
|
||||
Assert.assertEquals(0, annotations.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetElement() {
|
||||
AnnotatedElement element = Foo.class;
|
||||
RepeatableMetaAnnotatedElement<GenericAnnotationMapping> repeatableMetaAnnotatedElement = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), element, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
Assert.assertSame(element, repeatableMetaAnnotatedElement.getElement());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
RepeatableMetaAnnotatedElement<GenericAnnotationMapping> element = RepeatableMetaAnnotatedElement.create(
|
||||
RepeatableAnnotationCollector.standard(), Foo.class, (s, a) -> new GenericAnnotationMapping(a, Objects.isNull(s))
|
||||
);
|
||||
int count = 0;
|
||||
for (GenericAnnotationMapping mapping : element) {
|
||||
count++;
|
||||
}
|
||||
Assert.assertEquals(14, count);
|
||||
}
|
||||
|
||||
@Annotation4
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation1 {
|
||||
Annotation2[] value() default {};
|
||||
}
|
||||
|
||||
@Annotation4
|
||||
@Repeatable(Annotation1.class)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation2 {
|
||||
Annotation3[] value() default {};
|
||||
}
|
||||
|
||||
@Annotation4
|
||||
@Repeatable(Annotation2.class)
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation3 { }
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
private @interface Annotation4 { }
|
||||
|
||||
@Annotation1({
|
||||
@Annotation2({@Annotation3, @Annotation3}),
|
||||
@Annotation2({@Annotation3, @Annotation3})
|
||||
})
|
||||
private static class Foo {}
|
||||
|
||||
}
|
Reference in New Issue
Block a user