Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import java.lang.annotation.Annotation;
     18 import java.lang.reflect.Method;
     19 
     20 public class AnnotationTest extends AnnotationTestHelpers {
     21   public static void testAnnotationsByType() {
     22     System.out.println("==============================");
     23     System.out.println("Class annotations by type:");
     24     System.out.println("==============================");
     25 
     26     // Print associated annotations:
     27     // * A is directly present or repeatably present on an element E;
     28     // * No annotation of A is directly/repeatably present on an element
     29     //   AND E is a class AND A's type is inheritable, AND A is associated with its superclass.
     30     // (Looks through subtypes recursively only if there's 0 result at each level,
     31     // and the annotation is @Inheritable).
     32     printAnnotationsByType(Calendar.class, SingleUser.class);
     33     printAnnotationsByType(Calendars.class, SingleUser.class);
     34 
     35     printAnnotationsByType(Calendar.class, User.class);
     36     printAnnotationsByType(Calendars.class, User.class);
     37 
     38     printAnnotationsByType(Calendar.class, User2.class);  // Enforce ordering 'z,x,y'
     39     printAnnotationsByType(Calendars.class, User2.class);
     40 
     41     // NOTE:
     42     //    Order of outer-most annotations Calendars[C,C],S vs C,Calendars[C,C] is unspecified.
     43     //    In particular it's the order of #getDeclaredAnnotations which is completely unmentioned.
     44     //    The only requirement for #getAnnotationsByType is to have same ordering as
     45     //    #getDeclaredAnnotations.
     46     //    (Calendars[] itself has to maintain value() order).
     47     printAnnotationsByType(Calendar.class, UserComplex.class);  // Cs(C,C),C collapses into C,C,C.
     48     printAnnotationsByType(Calendars.class, UserComplex.class);
     49 
     50     printAnnotationsByType(Calendar.class, UserSub.class);
     51     printAnnotationsByType(Calendars.class, UserSub.class);
     52 
     53     printAnnotationsByType(Calendar.class, UserSub2.class);
     54     // The directly present "Calendar" annotation masks all the repeatably present
     55     // "Calendar" annotations coming from User.
     56     printAnnotationsByType(Calendars.class, UserSub2.class);
     57     // Edge case: UserSub2 doesn't directly have a Calendars annotation,
     58     // so it doesn't mask the "User" Calendars annotation.
     59 
     60     System.out.println("-----------------------------");
     61     System.out.println("-----------------------------");
     62 
     63   }
     64 
     65   public static void testDeclaredAnnotation() {
     66     System.out.println("==============================");
     67     System.out.println("Class declared annotation:");
     68     System.out.println("==============================");
     69 
     70     // Print directly present annotations:
     71     //
     72     // The element E has an annotation_item for it (accessible through an
     73     // annotations_directory_item) corresponding to an annotation A,
     74     // and A's type_idx must match that on the encoded_annotation (from the annotation_item).
     75     // (Does not look through the subtypes recursively)
     76     printDeclaredAnnotation(SingleUser.class, Calendar.class);
     77     printDeclaredAnnotation(SingleUser.class, Calendars.class);
     78 
     79     printDeclaredAnnotation(User.class, Calendar.class);
     80     printDeclaredAnnotation(User.class, Calendars.class);
     81 
     82     printDeclaredAnnotation(UserComplex.class, Calendar.class);
     83     printDeclaredAnnotation(UserComplex.class, Calendars.class);
     84 
     85     printDeclaredAnnotation(UserSub.class, Calendar.class);
     86     printDeclaredAnnotation(UserSub.class, Calendars.class);
     87 
     88     printDeclaredAnnotation(UserSub2.class, Calendar.class);
     89     printDeclaredAnnotation(UserSub2.class, Calendars.class);
     90 
     91     System.out.println("-----------------------------");
     92     System.out.println("-----------------------------");
     93   }
     94 
     95   public static void testDeclaredAnnotationsByType() {
     96     System.out.println("==============================");
     97     System.out.println("Declared class annotations by type:");
     98     System.out.println("==============================");
     99 
    100     // A is directly present or repeatably present on an element E;
    101     // -- (does not do any recursion for classes regardless of @Inherited)
    102     printDeclaredAnnotationsByType(Calendar.class, SingleUser.class);
    103     printDeclaredAnnotationsByType(Calendars.class, SingleUser.class);
    104 
    105     printDeclaredAnnotationsByType(Calendar.class, User.class);
    106     printDeclaredAnnotationsByType(Calendars.class, User.class);
    107 
    108     printDeclaredAnnotationsByType(Calendar.class, User2.class);  // Enforce ordering 'z,x,y'
    109     printDeclaredAnnotationsByType(Calendars.class, User2.class);
    110 
    111     printDeclaredAnnotationsByType(Calendar.class, UserComplex.class);
    112     printDeclaredAnnotationsByType(Calendars.class, UserComplex.class);
    113 
    114     printDeclaredAnnotationsByType(Calendar.class, UserSub.class);
    115     printDeclaredAnnotationsByType(Calendars.class, UserSub.class);
    116 
    117     printDeclaredAnnotationsByType(Calendar.class, UserSub2.class);
    118     // The directly present "Calendar" annotation masks all the repeatably present "Calendar"
    119     // annotations coming from User.
    120     printDeclaredAnnotationsByType(Calendars.class, UserSub2.class);
    121     // Edge case: UserSub2 doesn't directly have a Calendars annotation,
    122     // so it doesn't mask the "User" Calendars annotation.
    123 
    124     System.out.println("-----------------------------");
    125     System.out.println("-----------------------------");
    126   }
    127 
    128   // Print the annotation "annotationClass" that is associated with an element denoted by
    129   // "annotationUseClass."
    130   private static <A extends Annotation> void printAnnotationsByType(Class<A> annotationClass,
    131       Class<?> annotationUseClass) {
    132     A[] annotationsByType = annotationUseClass.getAnnotationsByType(annotationClass);
    133 
    134     String msg = "Annotations by type, defined by class "
    135         + annotationUseClass.getName() + " with annotation " + annotationClass.getName() + ": "
    136         + asString(annotationsByType);
    137 
    138 
    139     System.out.println(msg);
    140   }
    141 
    142   private static <A extends Annotation> void printDeclaredAnnotation(Class<?> annotationUseClass,
    143       Class<A> annotationDefClass) {
    144     A anno = annotationUseClass.getDeclaredAnnotation(annotationDefClass);
    145 
    146     String msg = asString(anno);
    147 
    148     System.out.println("Declared annotations by class " + annotationUseClass
    149         + ", annotation " + annotationDefClass + ": " + msg);
    150   }
    151 
    152   // Print the annotation "annotationClass" that is directly/indirectly present with an element
    153   // denoted by "annotationUseClass."
    154   private static <A extends Annotation> void printDeclaredAnnotationsByType(
    155       Class<A> annotationClass, Class<?> annotationUseClass) {
    156     A[] annotationsByType = annotationUseClass.getDeclaredAnnotationsByType(annotationClass);
    157 
    158     String msg = "Declared annnotations by type, defined by class " + annotationUseClass.getName()
    159         + " with annotation " + annotationClass.getName() + ": "
    160         + asString(annotationsByType);
    161 
    162     System.out.println(msg);
    163   }
    164 
    165   public static void testMethodAnnotationsByType() {
    166     System.out.println("==============================");
    167     System.out.println("Method annotations by type:");
    168     System.out.println("==============================");
    169 
    170     // Print associated annotations:
    171     // * A is directly present or repeatably present on an element E;
    172     // * No annotation of A is directly/repeatably present on an element AND E is a class
    173     //   AND A's type is inheritable, AND A is associated with its superclass.
    174     // (Looks through subtypes recursively only if there's 0 result at each level,
    175     // and the annotation is @Inheritable).
    176     printMethodAnnotationsByType(Calendar.class, "singleUser", AnnotationTestFixture.class);
    177     printMethodAnnotationsByType(Calendars.class, "singleUser", AnnotationTestFixture.class);
    178 
    179     printMethodAnnotationsByType(Calendar.class, "user", AnnotationTestFixture.class);
    180     printMethodAnnotationsByType(Calendars.class, "user", AnnotationTestFixture.class);
    181 
    182     printMethodAnnotationsByType(Calendar.class, "user2", AnnotationTestFixture.class);
    183     printMethodAnnotationsByType(Calendars.class, "user2", AnnotationTestFixture.class);
    184 
    185     printMethodAnnotationsByType(Calendar.class, "userComplex", AnnotationTestFixture.class);
    186     printMethodAnnotationsByType(Calendars.class, "userComplex", AnnotationTestFixture.class);
    187 
    188     System.out.println("-----------------------------");
    189     System.out.println("-----------------------------");
    190   }
    191 
    192   // Print the annotation "annotationClass" that is associated with an element denoted by
    193   // "annotationUseClass" method methodName.
    194   private static <A extends Annotation> void printMethodAnnotationsByType(Class<A> annotationClass,
    195       String methodName, Class<?> annotationUseClass) {
    196     Method m = null;
    197     try {
    198       m = annotationUseClass.getDeclaredMethod(methodName);
    199     } catch (Throwable t) {
    200       throw new AssertionError(t);
    201     }
    202     A[] annotationsByType = m.getAnnotationsByType(annotationClass);
    203 
    204     String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " +
    205       annotationClass.getName() + ": " +
    206       asString(annotationsByType);
    207 
    208     System.out.println(msg);
    209   }
    210 
    211   public static void testMethodDeclaredAnnotations() {
    212     System.out.println("==============================");
    213     System.out.println("Declared method annotations:");
    214     System.out.println("==============================");
    215 
    216     printMethodDeclaredAnnotation(Calendar.class, "singleUser", AnnotationTestFixture.class);
    217     printMethodDeclaredAnnotation(Calendars.class, "singleUser", AnnotationTestFixture.class);
    218 
    219     printMethodDeclaredAnnotation(Calendar.class, "user", AnnotationTestFixture.class);
    220     printMethodDeclaredAnnotation(Calendars.class, "user", AnnotationTestFixture.class);
    221 
    222     printMethodDeclaredAnnotation(Calendar.class, "user2", AnnotationTestFixture.class);
    223     printMethodDeclaredAnnotation(Calendars.class, "user2", AnnotationTestFixture.class);
    224 
    225     printMethodDeclaredAnnotation(Calendar.class, "userComplex", AnnotationTestFixture.class);
    226     printMethodDeclaredAnnotation(Calendars.class, "userComplex", AnnotationTestFixture.class);
    227 
    228     System.out.println("-----------------------------");
    229     System.out.println("-----------------------------");
    230   }
    231 
    232   // Print the annotation "annotationClass" that is associated with an element denoted by
    233   // methodName in annotationUseClass.
    234   private static <A extends Annotation> void printMethodDeclaredAnnotation(Class<A> annotationClass,
    235       String methodName, Class<?> annotationUseClass) {
    236     Method m = null;
    237     try {
    238       m = annotationUseClass.getDeclaredMethod(methodName);
    239     } catch (Throwable t) {
    240       throw new AssertionError(t);
    241     }
    242     Annotation annotationsByType = m.getDeclaredAnnotation(annotationClass);
    243 
    244     String msg = "Annotations declared by method " + m.getName() + " with annotation "
    245         + annotationClass.getName() + ": "
    246         + asString(annotationsByType);
    247 
    248     System.out.println(msg);
    249   }
    250 
    251   public static void testMethodDeclaredAnnotationsByType() {
    252     System.out.println("==============================");
    253     System.out.println("Declared method annotations by type:");
    254     System.out.println("==============================");
    255 
    256     printMethodDeclaredAnnotationByType(Calendar.class, "singleUser", AnnotationTestFixture.class);
    257     printMethodDeclaredAnnotationByType(Calendars.class, "singleUser", AnnotationTestFixture.class);
    258 
    259     printMethodDeclaredAnnotationByType(Calendar.class, "user", AnnotationTestFixture.class);
    260     printMethodDeclaredAnnotationByType(Calendars.class, "user", AnnotationTestFixture.class);
    261 
    262     printMethodDeclaredAnnotationByType(Calendar.class, "user2", AnnotationTestFixture.class);
    263     printMethodDeclaredAnnotationByType(Calendars.class, "user2", AnnotationTestFixture.class);
    264 
    265     printMethodDeclaredAnnotationByType(Calendar.class, "userComplex", AnnotationTestFixture.class);
    266     printMethodDeclaredAnnotationByType(Calendars.class, "userComplex",
    267         AnnotationTestFixture.class);
    268 
    269     System.out.println("-----------------------------");
    270     System.out.println("-----------------------------");
    271   }
    272 
    273   // Print the annotation "annotationClass" that is associated with an element denoted by
    274   // methodName in annotationUseClass.
    275   private static <A extends Annotation> void printMethodDeclaredAnnotationByType(
    276       Class<A> annotationClass, String methodName, Class<?> annotationUseClass) {
    277     Method m = null;
    278     try {
    279       m = annotationUseClass.getDeclaredMethod(methodName);
    280     } catch (Throwable t) {
    281       throw new AssertionError(t);
    282     }
    283     A[] annotationsByType = m.getDeclaredAnnotationsByType(annotationClass);
    284 
    285     String msg = "Annotations by type, defined by method " + m.getName() + " with annotation "
    286         + annotationClass.getName() + ": "
    287         + asString(annotationsByType);
    288 
    289     System.out.println(msg);
    290   }
    291 }
    292