/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class AnnotationTest extends AnnotationTestHelpers {
public static void testAnnotationsByType() {
System.out.println("==============================");
System.out.println("Class annotations by type:");
System.out.println("==============================");
// Print associated annotations:
// * A is directly present or repeatably present on an element E;
// * No annotation of A is directly/repeatably present on an element
// AND E is a class AND A's type is inheritable, AND A is associated with its superclass.
// (Looks through subtypes recursively only if there's 0 result at each level,
// and the annotation is @Inheritable).
printAnnotationsByType(Calendar.class, SingleUser.class);
printAnnotationsByType(Calendars.class, SingleUser.class);
printAnnotationsByType(Calendar.class, User.class);
printAnnotationsByType(Calendars.class, User.class);
printAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y'
printAnnotationsByType(Calendars.class, User2.class);
// NOTE:
// Order of outer-most annotations Calendars[C,C],S vs C,Calendars[C,C] is unspecified.
// In particular it's the order of #getDeclaredAnnotations which is completely unmentioned.
// The only requirement for #getAnnotationsByType is to have same ordering as
// #getDeclaredAnnotations.
// (Calendars[] itself has to maintain value() order).
printAnnotationsByType(Calendar.class, UserComplex.class); // Cs(C,C),C collapses into C,C,C.
printAnnotationsByType(Calendars.class, UserComplex.class);
printAnnotationsByType(Calendar.class, UserSub.class);
printAnnotationsByType(Calendars.class, UserSub.class);
printAnnotationsByType(Calendar.class, UserSub2.class);
// The directly present "Calendar" annotation masks all the repeatably present
// "Calendar" annotations coming from User.
printAnnotationsByType(Calendars.class, UserSub2.class);
// Edge case: UserSub2 doesn't directly have a Calendars annotation,
// so it doesn't mask the "User" Calendars annotation.
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
public static void testDeclaredAnnotation() {
System.out.println("==============================");
System.out.println("Class declared annotation:");
System.out.println("==============================");
// Print directly present annotations:
//
// The element E has an annotation_item for it (accessible through an
// annotations_directory_item) corresponding to an annotation A,
// and A's type_idx must match that on the encoded_annotation (from the annotation_item).
// (Does not look through the subtypes recursively)
printDeclaredAnnotation(SingleUser.class, Calendar.class);
printDeclaredAnnotation(SingleUser.class, Calendars.class);
printDeclaredAnnotation(User.class, Calendar.class);
printDeclaredAnnotation(User.class, Calendars.class);
printDeclaredAnnotation(UserComplex.class, Calendar.class);
printDeclaredAnnotation(UserComplex.class, Calendars.class);
printDeclaredAnnotation(UserSub.class, Calendar.class);
printDeclaredAnnotation(UserSub.class, Calendars.class);
printDeclaredAnnotation(UserSub2.class, Calendar.class);
printDeclaredAnnotation(UserSub2.class, Calendars.class);
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
public static void testDeclaredAnnotationsByType() {
System.out.println("==============================");
System.out.println("Declared class annotations by type:");
System.out.println("==============================");
// A is directly present or repeatably present on an element E;
// -- (does not do any recursion for classes regardless of @Inherited)
printDeclaredAnnotationsByType(Calendar.class, SingleUser.class);
printDeclaredAnnotationsByType(Calendars.class, SingleUser.class);
printDeclaredAnnotationsByType(Calendar.class, User.class);
printDeclaredAnnotationsByType(Calendars.class, User.class);
printDeclaredAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y'
printDeclaredAnnotationsByType(Calendars.class, User2.class);
printDeclaredAnnotationsByType(Calendar.class, UserComplex.class);
printDeclaredAnnotationsByType(Calendars.class, UserComplex.class);
printDeclaredAnnotationsByType(Calendar.class, UserSub.class);
printDeclaredAnnotationsByType(Calendars.class, UserSub.class);
printDeclaredAnnotationsByType(Calendar.class, UserSub2.class);
// The directly present "Calendar" annotation masks all the repeatably present "Calendar"
// annotations coming from User.
printDeclaredAnnotationsByType(Calendars.class, UserSub2.class);
// Edge case: UserSub2 doesn't directly have a Calendars annotation,
// so it doesn't mask the "User" Calendars annotation.
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
// Print the annotation "annotationClass" that is associated with an element denoted by
// "annotationUseClass."
private static <A extends Annotation> void printAnnotationsByType(Class<A> annotationClass,
Class<?> annotationUseClass) {
A[] annotationsByType = annotationUseClass.getAnnotationsByType(annotationClass);
String msg = "Annotations by type, defined by class "
+ annotationUseClass.getName() + " with annotation " + annotationClass.getName() + ": "
+ asString(annotationsByType);
System.out.println(msg);
}
private static <A extends Annotation> void printDeclaredAnnotation(Class<?> annotationUseClass,
Class<A> annotationDefClass) {
A anno = annotationUseClass.getDeclaredAnnotation(annotationDefClass);
String msg = asString(anno);
System.out.println("Declared annotations by class " + annotationUseClass
+ ", annotation " + annotationDefClass + ": " + msg);
}
// Print the annotation "annotationClass" that is directly/indirectly present with an element
// denoted by "annotationUseClass."
private static <A extends Annotation> void printDeclaredAnnotationsByType(
Class<A> annotationClass, Class<?> annotationUseClass) {
A[] annotationsByType = annotationUseClass.getDeclaredAnnotationsByType(annotationClass);
String msg = "Declared annnotations by type, defined by class " + annotationUseClass.getName()
+ " with annotation " + annotationClass.getName() + ": "
+ asString(annotationsByType);
System.out.println(msg);
}
public static void testMethodAnnotationsByType() {
System.out.println("==============================");
System.out.println("Method annotations by type:");
System.out.println("==============================");
// Print associated annotations:
// * A is directly present or repeatably present on an element E;
// * No annotation of A is directly/repeatably present on an element AND E is a class
// AND A's type is inheritable, AND A is associated with its superclass.
// (Looks through subtypes recursively only if there's 0 result at each level,
// and the annotation is @Inheritable).
printMethodAnnotationsByType(Calendar.class, "singleUser", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendars.class, "singleUser", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendar.class, "user", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendars.class, "user", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendar.class, "user2", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendars.class, "user2", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendar.class, "userComplex", AnnotationTestFixture.class);
printMethodAnnotationsByType(Calendars.class, "userComplex", AnnotationTestFixture.class);
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
// Print the annotation "annotationClass" that is associated with an element denoted by
// "annotationUseClass" method methodName.
private static <A extends Annotation> void printMethodAnnotationsByType(Class<A> annotationClass,
String methodName, Class<?> annotationUseClass) {
Method m = null;
try {
m = annotationUseClass.getDeclaredMethod(methodName);
} catch (Throwable t) {
throw new AssertionError(t);
}
A[] annotationsByType = m.getAnnotationsByType(annotationClass);
String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " +
annotationClass.getName() + ": " +
asString(annotationsByType);
System.out.println(msg);
}
public static void testMethodDeclaredAnnotations() {
System.out.println("==============================");
System.out.println("Declared method annotations:");
System.out.println("==============================");
printMethodDeclaredAnnotation(Calendar.class, "singleUser", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendars.class, "singleUser", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendar.class, "user", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendars.class, "user", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendar.class, "user2", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendars.class, "user2", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendar.class, "userComplex", AnnotationTestFixture.class);
printMethodDeclaredAnnotation(Calendars.class, "userComplex", AnnotationTestFixture.class);
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
// Print the annotation "annotationClass" that is associated with an element denoted by
// methodName in annotationUseClass.
private static <A extends Annotation> void printMethodDeclaredAnnotation(Class<A> annotationClass,
String methodName, Class<?> annotationUseClass) {
Method m = null;
try {
m = annotationUseClass.getDeclaredMethod(methodName);
} catch (Throwable t) {
throw new AssertionError(t);
}
Annotation annotationsByType = m.getDeclaredAnnotation(annotationClass);
String msg = "Annotations declared by method " + m.getName() + " with annotation "
+ annotationClass.getName() + ": "
+ asString(annotationsByType);
System.out.println(msg);
}
public static void testMethodDeclaredAnnotationsByType() {
System.out.println("==============================");
System.out.println("Declared method annotations by type:");
System.out.println("==============================");
printMethodDeclaredAnnotationByType(Calendar.class, "singleUser", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendars.class, "singleUser", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendar.class, "user", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendars.class, "user", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendar.class, "user2", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendars.class, "user2", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendar.class, "userComplex", AnnotationTestFixture.class);
printMethodDeclaredAnnotationByType(Calendars.class, "userComplex",
AnnotationTestFixture.class);
System.out.println("-----------------------------");
System.out.println("-----------------------------");
}
// Print the annotation "annotationClass" that is associated with an element denoted by
// methodName in annotationUseClass.
private static <A extends Annotation> void printMethodDeclaredAnnotationByType(
Class<A> annotationClass, String methodName, Class<?> annotationUseClass) {
Method m = null;
try {
m = annotationUseClass.getDeclaredMethod(methodName);
} catch (Throwable t) {
throw new AssertionError(t);
}
A[] annotationsByType = m.getDeclaredAnnotationsByType(annotationClass);
String msg = "Annotations by type, defined by method " + m.getName() + " with annotation "
+ annotationClass.getName() + ": "
+ asString(annotationsByType);
System.out.println(msg);
}
}