Igor Murashkin | df187e4 | 2016-02-01 11:43:26 -0800 | [diff] [blame] | 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 | } |