This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new aaf24eb Collections usage optimizations.
aaf24eb is described below
commit aaf24ebf755b90708c1af114ed12f48c54026002
Author: JamesBognar <[email protected]>
AuthorDate: Sun Mar 13 12:51:29 2022 -0400
Collections usage optimizations.
---
.../src/main/java/org/apache/juneau/ClassMeta.java | 62 +++++-
.../org/apache/juneau/internal/ArrayUtils.java | 15 ++
.../java/org/apache/juneau/reflect/ClassInfo.java | 140 +++++++++++-
.../test/java/org/apache/juneau/ClassMetaTest.java | 244 ++++++++++++---------
.../org/apache/juneau/reflect/ClassInfoTest.java | 38 +++-
5 files changed, 383 insertions(+), 116 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 81c02d8..7b49599 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -2091,14 +2091,62 @@ public final class ClassMeta<T> implements Type {
* @param action An action to perform on the entry.
* @return This object.
*/
- @SuppressWarnings("unchecked")
public <A extends Annotation> ClassMeta<T> forEachAnnotation(Class<A>
type, Predicate<A> filter, Consumer<A> action) {
- A[] array = (A[])annotationArrayMap.get(type);
+ A[] array = annotationArray(type);
if (array == null) {
- if (beanContext == null) {
+ if (beanContext == null)
info.forEachAnnotation(BeanContext.DEFAULT,
type, filter, action);
- return this;
- }
+ return this;
+ }
+ for (A a : array)
+ consume(filter, action, a);
+ return this;
+ }
+
+ /**
+ * Returns the first matching annotation on this class or parent
classes/interfaces in parent-to-child order.
+ *
+ * @param type The annotation to search for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be used. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> Optional<A> firstAnnotation(Class<A>
type, Predicate<A> filter) {
+ A[] array = annotationArray(type);
+ if (array == null) {
+ if (beanContext == null)
+ return
Optional.ofNullable(info.firstAnnotation(BeanContext.DEFAULT, type, filter));
+ return Optional.empty();
+ }
+ for (A a : array)
+ if (passes(filter, a))
+ return Optional.of(a);
+ return Optional.empty();
+ }
+
+ /**
+ * Returns the last matching annotation on this class or parent
classes/interfaces in parent-to-child order.
+ *
+ * @param type The annotation to search for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be used. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> Optional<A> lastAnnotation(Class<A> type,
Predicate<A> filter) {
+ A[] array = annotationArray(type);
+ if (array == null) {
+ if (beanContext == null)
+ return
Optional.ofNullable(info.lastAnnotation(BeanContext.DEFAULT, type, filter));
+ return Optional.empty();
+ }
+ for (int i = array.length-1; i >= 0; i--)
+ if (passes(filter, array[i]))
+ return Optional.of(array[i]);
+ return Optional.empty();
+ }
+
+ @SuppressWarnings("unchecked")
+ private <A extends Annotation> A[] annotationArray(Class<A> type) {
+ A[] array = (A[])annotationArrayMap.get(type);
+ if (array == null && beanContext != null) {
List<A> l = list();
info.forEachAnnotation(beanContext, type, x-> true, x
-> l.add(x));
array = (A[])Array.newInstance(type, l.size());
@@ -2106,9 +2154,7 @@ public final class ClassMeta<T> implements Type {
Array.set(array, i, l.get(i));
annotationArrayMap.put(type, array);
}
- for (A a : array)
- consume(filter, action, a);
- return this;
+ return array;
}
/**
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java
index 5ea415d..eb1df27 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ArrayUtils.java
@@ -348,4 +348,19 @@ public final class ArrayUtils {
public static final boolean isEmptyArray(Object[] array1, Object[]
array2) {
return isEmptyArray(array1) && isEmptyArray(array2);
}
+
+ /**
+ * Reverses the entries in an array.
+ *
+ * @param array The array to reverse.
+ * @return The same array.
+ */
+ public static final <T> T[] reverse(T[] array) {
+ for (int i = 0; i < array.length / 2; i++) {
+ T temp = array[i];
+ array[i] = array[array.length - i - 1];
+ array[array.length - i - 1] = temp;
+ }
+ return array;
+ }
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index c2c9cfb..6e72595 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -923,7 +923,7 @@ public final class ClassInfo {
* @return The matching annotations.
*/
public <A extends Annotation> List<A> getAnnotations(Class<A> type) {
- return getAnnotations(AnnotationProvider.DEFAULT, type);
+ return getAnnotations(null, type);
}
/**
@@ -951,7 +951,7 @@ public final class ClassInfo {
* @return This object.
*/
public <A extends Annotation> ClassInfo forEachAnnotation(Class<A>
type, Predicate<A> filter, Consumer<A> action) {
- return forEachAnnotation(AnnotationProvider.DEFAULT, type,
filter, action);
+ return forEachAnnotation(null, type, filter, action);
}
/**
@@ -961,8 +961,8 @@ public final class ClassInfo {
* Annotations are appended in the following orders:
* <ol>
* <li>On the package of this class.
- * <li>On interfaces ordered child-to-parent.
- * <li>On parent classes ordered child-to-parent.
+ * <li>On interfaces ordered parent-to-child.
+ * <li>On parent classes ordered parent-to-child.
* <li>On this class.
* </ol>
*
@@ -973,8 +973,6 @@ public final class ClassInfo {
* @return This object.
*/
public <A extends Annotation> ClassInfo
forEachAnnotation(AnnotationProvider annotationProvider, Class<A> type,
Predicate<A> filter, Consumer<A> action) {
- if (filter == null)
- filter = x->true;
if (annotationProvider == null)
annotationProvider = AnnotationProvider.DEFAULT;
A t2 = getPackageAnnotation(type);
@@ -990,6 +988,124 @@ public final class ClassInfo {
}
/**
+ * Returns the first matching annotation on this class and
superclasses/interfaces.
+ *
+ * <p>
+ * Annotations are searched in the following orders:
+ * <ol>
+ * <li>On the package of this class.
+ * <li>On interfaces ordered parent-to-child.
+ * <li>On parent classes ordered parent-to-child.
+ * <li>On this class.
+ * </ol>
+ *
+ * @param type The annotation to look for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be returned. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> A firstAnnotation(Class<A> type,
Predicate<A> filter) {
+ return firstAnnotation(null, type, filter);
+ }
+
+ /**
+ * Returns the first matching annotation on this class and
superclasses/interfaces.
+ *
+ * <p>
+ * Annotations are searched in the following orders:
+ * <ol>
+ * <li>On the package of this class.
+ * <li>On interfaces ordered parent-to-child.
+ * <li>On parent classes ordered parent-to-child.
+ * <li>On this class.
+ * </ol>
+ *
+ * @param annotationProvider The annotation provider.
+ * @param type The annotation to look for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be returned. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> A firstAnnotation(AnnotationProvider
annotationProvider, Class<A> type, Predicate<A> filter) {
+ if (annotationProvider == null)
+ annotationProvider = AnnotationProvider.DEFAULT;
+ A x = null;
+ x = getPackageAnnotation(type);
+ if (x != null && passes(filter, x))
+ return x;
+ ClassInfo[] interfaces = _getInterfaces();
+ for (int i = interfaces.length-1; i >= 0; i--) {
+ x = annotationProvider.firstAnnotation(type,
interfaces[i].inner(), filter);
+ if (x != null)
+ return x;
+ }
+ ClassInfo[] parents = _getParents();
+ for (int i = parents.length-1; i >= 0; i--) {
+ x = annotationProvider.firstAnnotation(type,
parents[i].inner(), filter);
+ if (x != null)
+ return x;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the last matching annotation on this class and
superclasses/interfaces.
+ *
+ * <p>
+ * Annotations are searched in the following orders:
+ * <ol>
+ * <li>On this class.
+ * <li>On parent classes ordered child-to-parent.
+ * <li>On interfaces ordered child-to-parent.
+ * <li>On the package of this class.
+ * </ol>
+ *
+ * @param type The annotation to look for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be returned. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> A lastAnnotation(Class<A> type,
Predicate<A> filter) {
+ return lastAnnotation(null, type, filter);
+ }
+
+ /**
+ * Returns the last matching annotation on this class and
superclasses/interfaces.
+ *
+ * <p>
+ * Annotations are searched in the following orders:
+ * <ol>
+ * <li>On this class.
+ * <li>On parent classes ordered child-to-parent.
+ * <li>On interfaces ordered child-to-parent.
+ * <li>On the package of this class.
+ * </ol>
+ *
+ * @param annotationProvider The annotation provider.
+ * @param type The annotation to look for.
+ * @param filter A predicate to apply to the entries to determine if
annotation should be returned. Can be <jk>null</jk>.
+ * @return This object.
+ */
+ public <A extends Annotation> A lastAnnotation(AnnotationProvider
annotationProvider, Class<A> type, Predicate<A> filter) {
+ if (annotationProvider == null)
+ annotationProvider = AnnotationProvider.DEFAULT;
+ A x = null;
+ ClassInfo[] parents = _getParents();
+ for (int i = 0; i < parents.length; i++) {
+ x = annotationProvider.lastAnnotation(type,
parents[i].inner(), filter);
+ if (x != null)
+ return x;
+ }
+ ClassInfo[] interfaces = _getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ x = annotationProvider.lastAnnotation(type,
interfaces[i].inner(), filter);
+ if (x != null)
+ return x;
+ }
+ x = getPackageAnnotation(type);
+ if (x != null && passes(filter, x))
+ return x;
+ return null;
+ }
+
+ /**
* Finds the annotation of the specified type defined on this class or
parent class/interface.
*
* <p>
@@ -1001,7 +1117,7 @@ public final class ClassInfo {
* @return The annotation if found, or <jk>null</jk> if not.
*/
public <A extends Annotation> A getAnnotation(Class<A> type) {
- return getAnnotation(AnnotationProvider.DEFAULT, type);
+ return getAnnotation(null, type);
}
/**
@@ -1026,7 +1142,7 @@ public final class ClassInfo {
* @return The <jk>true</jk> if annotation if found.
*/
public <A extends Annotation> boolean hasAnnotation(Class<A> type) {
- return hasAnnotation(AnnotationProvider.DEFAULT, type);
+ return hasAnnotation(null, type);
}
/**
@@ -1047,6 +1163,8 @@ public final class ClassInfo {
* @return The <jk>true</jk> if annotation if found.
*/
public <A extends Annotation> boolean hasAnnotation(AnnotationProvider
annotationProvider, Class<A> type) {
+ if (annotationProvider == null)
+ annotationProvider = AnnotationProvider.DEFAULT;
return annotationProvider.firstAnnotation(type, c, x -> true)
!= null;
}
@@ -1070,7 +1188,7 @@ public final class ClassInfo {
* @return This object.
*/
public <A extends Annotation> A getAnnotation(Class<A> type,
Predicate<A> filter) {
- return getAnnotation(AnnotationProvider.DEFAULT, type, filter);
+ return getAnnotation(null, type, filter);
}
/**
@@ -1133,6 +1251,8 @@ public final class ClassInfo {
private <A extends Annotation> A findAnnotation(AnnotationProvider ap,
Class<A> a) {
if (a == null)
return null;
+ if (ap == null)
+ ap = AnnotationProvider.DEFAULT;
A t = ap.firstDeclaredAnnotation(a, c, x -> true);
if (t != null)
return t;
@@ -1151,6 +1271,8 @@ public final class ClassInfo {
}
private <A extends Annotation> A getAnnotation(AnnotationProvider ap,
Class<A> a, Predicate<A> filter) {
+ if (ap == null)
+ ap = AnnotationProvider.DEFAULT;
A t2 = getPackageAnnotation(a);
if (t2 != null && filter.test(t2))
return t2;
diff --git a/juneau-utest/src/test/java/org/apache/juneau/ClassMetaTest.java
b/juneau-utest/src/test/java/org/apache/juneau/ClassMetaTest.java
index d6bb88a..d382d16 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/ClassMetaTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/ClassMetaTest.java
@@ -12,11 +12,14 @@
//
***************************************************************************************************************************
package org.apache.juneau;
+import static org.apache.juneau.internal.CollectionUtils.*;
import static org.junit.Assert.*;
import static org.junit.runners.MethodSorters.*;
+import static org.apache.juneau.assertions.Assertions.*;
import java.util.*;
+import org.apache.juneau.reflect.ClassInfoTest.*;
import org.apache.juneau.swap.*;
import org.junit.*;
@@ -26,13 +29,14 @@ public class ClassMetaTest {
BeanContext bc = BeanContext.DEFAULT;
-
//====================================================================================================
- // Map<String,String> field
-
//====================================================================================================
+
//-----------------------------------------------------------------------------------------------------------------
+ // Basic tests
+
//-----------------------------------------------------------------------------------------------------------------
+
public Map<String,String> fa;
@Test
- public void testMap() throws Exception {
+ public void a01_map() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("fa").getGenericType());
assertEquals("java.util.Map<java.lang.String,java.lang.String>", t.toString());
assertTrue(t.isMap());
@@ -43,77 +47,72 @@ public class ClassMetaTest {
assertEquals(String.class, t.getValueType().getInnerClass());
}
-
//====================================================================================================
- // String field
-
//====================================================================================================
public String fb;
@Test
- public void testString() throws Exception {
+ public void a02_string() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("fb").getGenericType());
assertEquals(String.class, t.getInnerClass());
t = bc.getClassMeta(this.getClass().getField("fb").getType());
assertEquals(String.class, t.getInnerClass());
}
-
//====================================================================================================
- // Map<String,Map<String,Integer>> field
-
//====================================================================================================
public Map<String,Map<String,Integer>> fc;
@Test
- public void testMapWithMapValues() throws Exception {
+ public void a03_mapWithMapValues() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("fc").getGenericType());
assertEquals("java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Integer>>",
t.toString());
t = bc.getClassMeta(this.getClass().getField("fc").getType());
assertEquals("java.util.Map", t.toString());
}
-
//====================================================================================================
- // List<Map<String,List>> field
-
//====================================================================================================
public List<Map<String,List>> fd;
@Test
- public void testListWithMapValues() throws Exception {
+ public void a04_listWithMapValues() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("fd").getGenericType());
assertEquals("java.util.List<java.util.Map<java.lang.String,java.util.List>>",
t.toString());
}
-
//====================================================================================================
- // List<? extends String> field, List<? super String> field
-
//====================================================================================================
public List<? extends String> fe1;
public List<? super String> fe2;
@Test
- public void testListWithUpperBoundGenericEntryTypes() throws Exception {
+ public void a05_listWithUpperBoundGenericEntryTypes() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("fe1").getGenericType());
assertEquals("java.util.List", t.toString());
t =
bc.getClassMeta(this.getClass().getField("fe2").getGenericType());
assertEquals("java.util.List", t.toString());
}
-
//====================================================================================================
- // Bean extends HashMap<String,Object> field
-
//====================================================================================================
public class G extends HashMap<String,Object> {}
public G g;
@Test
- public void testBeanExtendsMap() throws Exception {
+ public void a06_beanExtendsMap() throws Exception {
ClassMeta t =
bc.getClassMeta(this.getClass().getField("g").getGenericType());
assertEquals("org.apache.juneau.ClassMetaTest$G<java.lang.String,java.lang.Object>",
t.toString());
assertTrue(t.isMap());
assertFalse(t.isCollection());
}
-
//====================================================================================================
- // testSwaps
+
//-----------------------------------------------------------------------------------------------------------------
+ // Swaps
// Ensure swaps on parent and child classes are properly detected.
-
//====================================================================================================
+
//-----------------------------------------------------------------------------------------------------------------
+
+ public interface BI1 {}
+ public class BC1 implements BI1 {}
+ public interface BI2 extends BI1 {}
+ public class BC2 extends BC1 implements BI2 {}
+ public static class BC1Swap extends ObjectSwap<BC1,Map> {}
+ public static class BI1Swap extends ObjectSwap<BI1,Map> {}
+ public static class BC2Swap extends ObjectSwap<BC2,Map> {}
+ public static class BI2Swap extends ObjectSwap<BI2,Map> {}
+
@Test
- public void testSwaps() throws Exception {
+ public void b01_swaps() throws Exception {
BeanContext bc;
ClassMeta<?> ooo, hi1, hc1, hi2, hc2;
BeanSession bs;
@@ -121,10 +120,10 @@ public class ClassMetaTest {
bc = BeanContext.DEFAULT;
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertFalse(ooo.hasChildSwaps());
assertFalse(hi1.hasChildSwaps());
assertFalse(hc1.hasChildSwaps());
@@ -136,41 +135,41 @@ public class ClassMetaTest {
assertNull(hi2.getSwap(bs));
assertNull(hc2.getSwap(bs));
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
- assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
HI1.class);
- assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
HC1.class);
- assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
HI2.class);
- assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
HC2.class);
+ assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
BI1.class);
+ assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
BC1.class);
+ assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
BI2.class);
+ assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
BC2.class);
- bc = BeanContext.create().swaps(HI1Swap.class).build();
+ bc = BeanContext.create().swaps(BI1Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertFalse(hc1.hasChildSwaps());
assertFalse(hi2.hasChildSwaps());
assertFalse(hc2.hasChildSwaps());
assertNull(ooo.getSwap(bs));
- assertEquals(hi1.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hc1.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hi2.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hc2.getSwap(bs).getClass(), HI1Swap.class);
+ assertEquals(hi1.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hc1.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hi2.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BI1Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- bc = BeanContext.create().swaps(HC1Swap.class).build();
+ bc = BeanContext.create().swaps(BC1Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertTrue(hc1.hasChildSwaps());
@@ -178,22 +177,22 @@ public class ClassMetaTest {
assertFalse(hc2.hasChildSwaps());
assertNull(ooo.getSwap(bs));
assertNull(hi1.getSwap(bs));
- assertEquals(hc1.getSwap(bs).getClass(), HC1Swap.class);
+ assertEquals(hc1.getSwap(bs).getClass(), BC1Swap.class);
assertNull(hi2.getSwap(bs));
- assertEquals(hc2.getSwap(bs).getClass(), HC1Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BC1Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
- assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
HI1.class);
+ assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
BI1.class);
assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
HI2.class);
+ assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
BI2.class);
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- bc = BeanContext.create().swaps(HI2Swap.class).build();
+ bc = BeanContext.create().swaps(BI2Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertFalse(hc1.hasChildSwaps());
@@ -202,21 +201,21 @@ public class ClassMetaTest {
assertNull(ooo.getSwap(bs));
assertNull(hi1.getSwap(bs));
assertNull(hc1.getSwap(bs));
- assertEquals(hi2.getSwap(bs).getClass(), HI2Swap.class);
- assertEquals(hc2.getSwap(bs).getClass(), HI2Swap.class);
+ assertEquals(hi2.getSwap(bs).getClass(), BI2Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BI2Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
- assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
HI1.class);
- assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
HC1.class);
+ assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
BI1.class);
+ assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
BC1.class);
assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- bc = BeanContext.create().swaps(HC2Swap.class).build();
+ bc = BeanContext.create().swaps(BC2Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertTrue(hc1.hasChildSwaps());
@@ -226,53 +225,53 @@ public class ClassMetaTest {
assertNull(hi1.getSwap(bs));
assertNull(hc1.getSwap(bs));
assertNull(hi2.getSwap(bs));
- assertEquals(hc2.getSwap(bs).getClass(), HC2Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BC2Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
- assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
HI1.class);
- assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
HC1.class);
- assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
HI2.class);
+ assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
BI1.class);
+ assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
BC1.class);
+ assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
BI2.class);
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- bc =
BeanContext.create().swaps(HI1Swap.class,HC1Swap.class,HI2Swap.class,
HC2Swap.class).build();
+ bc =
BeanContext.create().swaps(BI1Swap.class,BC1Swap.class,BI2Swap.class,
BC2Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertTrue(hc1.hasChildSwaps());
assertTrue(hi2.hasChildSwaps());
assertTrue(hc2.hasChildSwaps());
assertNull(ooo.getSwap(bs));
- assertEquals(hi1.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hc1.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hi2.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hc2.getSwap(bs).getClass(), HI1Swap.class);
+ assertEquals(hi1.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hc1.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hi2.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BI1Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hi2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
- bc =
BeanContext.create().swaps(HC2Swap.class,HI2Swap.class,HC1Swap.class,
HI1Swap.class).build();
+ bc =
BeanContext.create().swaps(BC2Swap.class,BI2Swap.class,BC1Swap.class,
BI1Swap.class).build();
bs = bc.getSession();
ooo = bc.getClassMeta(Object.class);
- hi1 = bc.getClassMeta(HI1.class);
- hc1 = bc.getClassMeta(HC1.class);
- hi2 = bc.getClassMeta(HI2.class);
- hc2 = bc.getClassMeta(HC2.class);
+ hi1 = bc.getClassMeta(BI1.class);
+ hc1 = bc.getClassMeta(BC1.class);
+ hi2 = bc.getClassMeta(BI2.class);
+ hc2 = bc.getClassMeta(BC2.class);
assertTrue(ooo.hasChildSwaps());
assertTrue(hi1.hasChildSwaps());
assertTrue(hc1.hasChildSwaps());
assertTrue(hi2.hasChildSwaps());
assertTrue(hc2.hasChildSwaps());
assertNull(ooo.getSwap(bs));
- assertEquals(hi1.getSwap(bs).getClass(), HI1Swap.class);
- assertEquals(hc1.getSwap(bs).getClass(), HC1Swap.class);
- assertEquals(hi2.getSwap(bs).getClass(), HI2Swap.class);
- assertEquals(hc2.getSwap(bs).getClass(), HC2Swap.class);
+ assertEquals(hi1.getSwap(bs).getClass(), BI1Swap.class);
+ assertEquals(hc1.getSwap(bs).getClass(), BC1Swap.class);
+ assertEquals(hi2.getSwap(bs).getClass(), BI2Swap.class);
+ assertEquals(hc2.getSwap(bs).getClass(), BC2Swap.class);
assertEquals(ooo.getSerializedClassMeta(bs).getInnerClass(),
Object.class);
assertEquals(hi1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
assertEquals(hc1.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
@@ -280,12 +279,61 @@ public class ClassMetaTest {
assertEquals(hc2.getSerializedClassMeta(bs).getInnerClass(),
Map.class);
}
- public interface HI1 {}
- public class HC1 implements HI1 {}
- public interface HI2 extends HI1 {}
- public class HC2 extends HC1 implements HI2 {}
- public static class HC1Swap extends ObjectSwap<HC1,Map> {}
- public static class HI1Swap extends ObjectSwap<HI1,Map> {}
- public static class HC2Swap extends ObjectSwap<HC2,Map> {}
- public static class HI2Swap extends ObjectSwap<HI2,Map> {}
+
//-----------------------------------------------------------------------------------------------------------------
+ // Annotations
+
//-----------------------------------------------------------------------------------------------------------------
+
+ @A(1) static interface CI1 {}
+ @A(2) static interface CI2 extends CI1 {}
+ @A(3) static interface CI3 {}
+ @A(4) static interface CI4 {}
+ @A(5) static class C1 implements CI1, CI2 {}
+ @A(6) static class C2 extends C1 implements CI3 {}
+ @A(7) static class C3 extends C2 {}
+ static class C4 extends C3 {}
+ static class C5 implements CI3 {}
+
+ @Test
+ public void forEachAnnotation() {
+ ClassMeta<?> c3 = bc.getClassMeta(C3.class);
+ ClassMeta<?> c4 = bc.getClassMeta(C4.class);
+ ClassMeta<?> c5 = bc.getClassMeta(C5.class);
+
+ List<Integer> l1 = list();
+ c3.forEachAnnotation(A.class, null, x -> l1.add(x.value()));
+ assertList(l1).asCdl().isString("2,1,3,5,6,7");
+
+ List<Integer> l2 = list();
+ c4.forEachAnnotation(A.class, null, x -> l2.add(x.value()));
+ assertList(l2).asCdl().isString("2,1,3,5,6,7");
+
+ List<Integer> l3 = list();
+ c5.forEachAnnotation(A.class, null, x -> l3.add(x.value()));
+ assertList(l3).asCdl().isString("3");
+
+ List<Integer> l4 = list();
+ c3.forEachAnnotation(A.class, x -> x.value() == 5, x ->
l4.add(x.value()));
+ assertList(l4).asCdl().isString("5");
+ }
+
+ @Test
+ public void firstAnnotation() {
+ ClassMeta<?> c3 = bc.getClassMeta(C3.class);
+ ClassMeta<?> c4 = bc.getClassMeta(C4.class);
+ ClassMeta<?> c5 = bc.getClassMeta(C5.class);
+ assertInteger(c3.firstAnnotation(A.class,
null).get().value()).is(2);
+ assertInteger(c4.firstAnnotation(A.class,
null).get().value()).is(2);
+ assertInteger(c5.firstAnnotation(A.class,
null).get().value()).is(3);
+ assertInteger(c3.firstAnnotation(A.class, x -> x.value() ==
5).get().value()).is(5);
+ }
+ @Test
+ public void lastAnnotation() {
+ ClassMeta<?> c3 = bc.getClassMeta(C3.class);
+ ClassMeta<?> c4 = bc.getClassMeta(C4.class);
+ ClassMeta<?> c5 = bc.getClassMeta(C5.class);
+ assertInteger(c3.lastAnnotation(A.class,
null).get().value()).is(7);
+ assertInteger(c4.lastAnnotation(A.class,
null).get().value()).is(7);
+ assertInteger(c5.lastAnnotation(A.class,
null).get().value()).is(3);
+ assertInteger(c3.lastAnnotation(A.class, x -> x.value() ==
5).get().value()).is(5);
+ }
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
b/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
index 993154f..0ed2efd 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/reflect/ClassInfoTest.java
@@ -625,8 +625,44 @@ public class ClassInfoTest {
}
@Test
- public void getAnnotationsParentFirst() {
+ public void getAnnotations() {
check("@A(2),@A(1),@A(3),@A(5),@A(6),@A(7)",
g3.getAnnotations(A.class));
+ check("@A(2),@A(1),@A(3),@A(5),@A(6),@A(7)",
g4.getAnnotations(A.class));
+ check("@A(3)", g5.getAnnotations(A.class));
+ }
+
+ @Test
+ public void forEachAnnotation() {
+ List<Integer> l1 = list();
+ g3.forEachAnnotation(A.class, null, x -> l1.add(x.value()));
+ assertList(l1).asCdl().isString("2,1,3,5,6,7");
+
+ List<Integer> l2 = list();
+ g4.forEachAnnotation(A.class, null, x -> l2.add(x.value()));
+ assertList(l2).asCdl().isString("2,1,3,5,6,7");
+
+ List<Integer> l3 = list();
+ g5.forEachAnnotation(A.class, null, x -> l3.add(x.value()));
+ assertList(l3).asCdl().isString("3");
+
+ List<Integer> l4 = list();
+ g3.forEachAnnotation(A.class, x -> x.value() == 5, x ->
l4.add(x.value()));
+ assertList(l4).asCdl().isString("5");
+ }
+
+ @Test
+ public void firstAnnotation() {
+ assertInteger(g3.firstAnnotation(A.class, null).value()).is(2);
+ assertInteger(g4.firstAnnotation(A.class, null).value()).is(2);
+ assertInteger(g5.firstAnnotation(A.class, null).value()).is(3);
+ assertInteger(g3.firstAnnotation(A.class, x -> x.value() ==
5).value()).is(5);
+ }
+ @Test
+ public void lastAnnotation() {
+ assertInteger(g3.lastAnnotation(A.class, null).value()).is(7);
+ assertInteger(g4.lastAnnotation(A.class, null).value()).is(7);
+ assertInteger(g5.lastAnnotation(A.class, null).value()).is(3);
+ assertInteger(g3.lastAnnotation(A.class, x -> x.value() ==
5).value()).is(5);
}
@Test