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 { testAnnotationsByType()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 testDeclaredAnnotation()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 testDeclaredAnnotationsByType()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." printAnnotationsByType(Class<A> annotationClass, Class<?> 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 printDeclaredAnnotation(Class<?> annotationUseClass, Class<A> annotationDefClass)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." printDeclaredAnnotationsByType( Class<A> annotationClass, Class<?> 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 testMethodAnnotationsByType()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. printMethodAnnotationsByType(Class<A> annotationClass, String methodName, Class<?> annotationUseClass)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 testMethodDeclaredAnnotations()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. printMethodDeclaredAnnotation(Class<A> annotationClass, String methodName, Class<?> 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 testMethodDeclaredAnnotationsByType()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. printMethodDeclaredAnnotationByType( Class<A> annotationClass, String methodName, Class<?> 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