/* * 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 void printAnnotationsByType(Class 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 void printDeclaredAnnotation(Class annotationUseClass, Class 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 void printDeclaredAnnotationsByType( Class 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 void printMethodAnnotationsByType(Class 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 void printMethodDeclaredAnnotation(Class 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 void printMethodDeclaredAnnotationByType( Class 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); } }