1 /*
2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.reflect.annotation;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.Map;
34
35 import static sun.reflect.annotation.TypeAnnotation.*;
36
37 public final class AnnotatedTypeFactory {
38 /**
39 * Create an AnnotatedType.
40 *
41 * @param type the type this AnnotatedType corresponds to
42 * @param currentLoc the location this AnnotatedType corresponds to
43 * @param actualTypeAnnos the type annotations this AnnotatedType has
44 * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
45 * as the AnnotatedType being built
46 * @param decl the declaration having the type use this AnnotatedType
47 * corresponds to
48 */
49 public static AnnotatedType buildAnnotatedType(Type type,
50 LocationInfo currentLoc,
51 TypeAnnotation[] actualTypeAnnos,
52 TypeAnnotation[] allOnSameTarget,
53 AnnotatedElement decl) {
185
186 Class<?> inner = (Class<?>)type;
187 Class<?> owner = inner.getDeclaringClass();
188 if (owner == null) // top-level, local or anonymous
189 return null;
190 if (inner.isPrimitive() || inner == Void.TYPE)
191 return null;
192
193 LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
194 TypeAnnotation[]all = getTypeAnnotations();
195 List<TypeAnnotation> l = new ArrayList<>(all.length);
196
197 for (TypeAnnotation t : all)
198 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
199 l.add(t);
200
201 return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
202
203 }
204
205 // Implementation details
206 final LocationInfo getLocation() {
207 return location;
208 }
209 final TypeAnnotation[] getTypeAnnotations() {
210 return allOnSameTargetTypeAnnotations;
211 }
212 final AnnotatedElement getDecl() {
213 return decl;
214 }
215 }
216
217 private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
218 AnnotatedArrayTypeImpl(Type type, LocationInfo location,
219 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
220 AnnotatedElement decl) {
221 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
222 }
223
224 @Override
227 return AnnotatedTypeFactory.buildAnnotatedType(t,
228 nestingForType(t, getLocation().pushArray()),
229 getTypeAnnotations(),
230 getTypeAnnotations(),
231 getDecl());
232 }
233
234 @Override
235 public AnnotatedType getAnnotatedOwnerType() {
236 return null;
237 }
238
239 private Type getComponentType() {
240 Type t = getType();
241 if (t instanceof Class) {
242 Class<?> c = (Class)t;
243 return c.getComponentType();
244 }
245 return ((GenericArrayType)t).getGenericComponentType();
246 }
247 }
248
249 private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
250 AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
251 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
252 AnnotatedElement decl) {
253 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
254 }
255
256 @Override
257 public AnnotatedType[] getAnnotatedBounds() {
258 return getTypeVariable().getAnnotatedBounds();
259 }
260
261 @Override
262 public AnnotatedType getAnnotatedOwnerType() {
263 return null;
264 }
265
266 private TypeVariable<?> getTypeVariable() {
267 return (TypeVariable)getType();
268 }
269 }
270
271 private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl
272 implements AnnotatedParameterizedType {
273 AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
274 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
275 AnnotatedElement decl) {
276 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
277 }
278
279 @Override
280 public AnnotatedType[] getAnnotatedActualTypeArguments() {
281 Type[] arguments = getParameterizedType().getActualTypeArguments();
282 AnnotatedType[] res = new AnnotatedType[arguments.length];
283 Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
284 int initialCapacity = getTypeAnnotations().length;
285 for (int i = 0; i < res.length; i++) {
286 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
287 LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
288 for (TypeAnnotation t : getTypeAnnotations())
299
300 @Override
301 public AnnotatedType getAnnotatedOwnerType() {
302 Type owner = getParameterizedType().getOwnerType();
303 if (owner == null)
304 return null;
305 LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
306 TypeAnnotation[]all = getTypeAnnotations();
307 List<TypeAnnotation> l = new ArrayList<>(all.length);
308
309 for (TypeAnnotation t : all)
310 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
311 l.add(t);
312
313 return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
314 }
315
316 private ParameterizedType getParameterizedType() {
317 return (ParameterizedType)getType();
318 }
319 }
320
321 private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
322 private final boolean hasUpperBounds;
323 AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
324 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
325 AnnotatedElement decl) {
326 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
327 hasUpperBounds = (type.getLowerBounds().length == 0);
328 }
329
330 @Override
331 public AnnotatedType[] getAnnotatedUpperBounds() {
332 if (!hasUpperBounds()) {
333 return new AnnotatedType[] { buildAnnotatedType(Object.class,
334 LocationInfo.BASE_LOCATION,
335 EMPTY_TYPE_ANNOTATION_ARRAY,
336 EMPTY_TYPE_ANNOTATION_ARRAY,
337 null)
338 };
360 LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
361 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
362 for (TypeAnnotation t : getTypeAnnotations())
363 if (t.getLocationInfo().isSameLocationInfo(newLoc))
364 l.add(t);
365 res[i] = buildAnnotatedType(bounds[i],
366 newLoc,
367 l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
368 getTypeAnnotations(),
369 getDecl());
370 }
371 return res;
372 }
373
374 private WildcardType getWildcardType() {
375 return (WildcardType)getType();
376 }
377
378 private boolean hasUpperBounds() {
379 return hasUpperBounds;
380 }
381 }
382 }
|
1 /*
2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.reflect.annotation;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Objects;
35 import java.util.StringJoiner;
36
37 import static sun.reflect.annotation.TypeAnnotation.*;
38
39 public final class AnnotatedTypeFactory {
40 /**
41 * Create an AnnotatedType.
42 *
43 * @param type the type this AnnotatedType corresponds to
44 * @param currentLoc the location this AnnotatedType corresponds to
45 * @param actualTypeAnnos the type annotations this AnnotatedType has
46 * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
47 * as the AnnotatedType being built
48 * @param decl the declaration having the type use this AnnotatedType
49 * corresponds to
50 */
51 public static AnnotatedType buildAnnotatedType(Type type,
52 LocationInfo currentLoc,
53 TypeAnnotation[] actualTypeAnnos,
54 TypeAnnotation[] allOnSameTarget,
55 AnnotatedElement decl) {
187
188 Class<?> inner = (Class<?>)type;
189 Class<?> owner = inner.getDeclaringClass();
190 if (owner == null) // top-level, local or anonymous
191 return null;
192 if (inner.isPrimitive() || inner == Void.TYPE)
193 return null;
194
195 LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
196 TypeAnnotation[]all = getTypeAnnotations();
197 List<TypeAnnotation> l = new ArrayList<>(all.length);
198
199 for (TypeAnnotation t : all)
200 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
201 l.add(t);
202
203 return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
204
205 }
206
207 @Override // java.lang.Object
208 public String toString() {
209 // Reusable toString implementation, but needs to be
210 // specialized for quirks of arrays.
211 return annotationsToString(getAnnotations(), false) + type.toString();
212 }
213
214 protected String annotationsToString(Annotation[] annotations, boolean leadingSpace) {
215 if (annotations != null && annotations.length > 0) {
216 StringJoiner sj = new StringJoiner(" ");
217 if (leadingSpace) {
218 sj.add(""); // Add a space
219 }
220
221 for (Annotation annotation : annotations) {
222 sj.add(annotation.toString());
223 }
224
225 if (!leadingSpace) {
226 sj.add("");
227 }
228 return sj.toString();
229 } else {
230 return "";
231 }
232 }
233
234 protected boolean equalsTypeAndAnnotations(AnnotatedType that) {
235 return getType().equals(that.getType()) &&
236 // Treat ordering of annotations as significant
237 Arrays.equals(getAnnotations(), that.getAnnotations()) &&
238 Objects.equals(getAnnotatedOwnerType(), that.getAnnotatedOwnerType());
239 }
240
241 int baseHashCode() {
242 return type.hashCode() ^
243 // Acceptable to use Objects.hash rather than
244 // Arrays.deepHashCode since the elements of the array
245 // are not themselves arrays.
246 Objects.hash((Object[])getAnnotations()) ^
247 Objects.hash(getAnnotatedOwnerType());
248 }
249
250 @Override
251 public boolean equals(Object o) {
252 if (o instanceof AnnotatedType &&
253 !(o instanceof AnnotatedArrayType) &&
254 !(o instanceof AnnotatedTypeVariable) &&
255 !(o instanceof AnnotatedParameterizedType) &&
256 !(o instanceof AnnotatedWildcardType)) {
257 AnnotatedType that = (AnnotatedType) o;
258 return equalsTypeAndAnnotations(that);
259 } else {
260 return false;
261 }
262 }
263
264 @Override
265 public int hashCode() {
266 return baseHashCode();
267 }
268
269 // Implementation details
270 final LocationInfo getLocation() {
271 return location;
272 }
273 final TypeAnnotation[] getTypeAnnotations() {
274 return allOnSameTargetTypeAnnotations;
275 }
276 final AnnotatedElement getDecl() {
277 return decl;
278 }
279 }
280
281 private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
282 AnnotatedArrayTypeImpl(Type type, LocationInfo location,
283 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
284 AnnotatedElement decl) {
285 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
286 }
287
288 @Override
291 return AnnotatedTypeFactory.buildAnnotatedType(t,
292 nestingForType(t, getLocation().pushArray()),
293 getTypeAnnotations(),
294 getTypeAnnotations(),
295 getDecl());
296 }
297
298 @Override
299 public AnnotatedType getAnnotatedOwnerType() {
300 return null;
301 }
302
303 private Type getComponentType() {
304 Type t = getType();
305 if (t instanceof Class) {
306 Class<?> c = (Class)t;
307 return c.getComponentType();
308 }
309 return ((GenericArrayType)t).getGenericComponentType();
310 }
311
312 @Override
313 public String toString() {
314 // To annotate the full type of an array, the annotations
315 // are placed between the type and the brackets. For
316 // example, to annotate an array of Strings, the syntax used is
317 //
318 // String @TypeAnnotation []
319 //
320 // and *not*
321 //
322 // @TypeAnnotation String[].
323 //
324 // The toString output should strive to be reusable in
325 // source code. Therefore, the general logic of putting
326 // the annotations before a textual representation of the
327 // type need to be overridden for arrays.
328 StringBuilder sb = new StringBuilder();
329
330 AnnotatedType componentType = this;
331 while (componentType instanceof AnnotatedArrayType) {
332 AnnotatedArrayType annotatedArrayType = (AnnotatedArrayType) componentType;
333 sb.append(annotationsToString(annotatedArrayType.getAnnotations(), true) + "[]");
334 componentType = annotatedArrayType.getAnnotatedGenericComponentType();
335 }
336
337 sb.insert(0, componentType.toString());
338 return sb.toString();
339 }
340
341 @Override
342 public boolean equals(Object o) {
343 if (o instanceof AnnotatedArrayType) {
344 AnnotatedArrayType that = (AnnotatedArrayType) o;
345 return equalsTypeAndAnnotations(that) &&
346 Objects.equals(getAnnotatedGenericComponentType(),
347 that.getAnnotatedGenericComponentType());
348 } else {
349 return false;
350 }
351 }
352
353 @Override
354 public int hashCode() {
355 return baseHashCode() ^ getAnnotatedGenericComponentType().hashCode();
356 }
357 }
358
359 private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
360 AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location,
361 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
362 AnnotatedElement decl) {
363 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
364 }
365
366 @Override
367 public AnnotatedType[] getAnnotatedBounds() {
368 return getTypeVariable().getAnnotatedBounds();
369 }
370
371 @Override
372 public AnnotatedType getAnnotatedOwnerType() {
373 return null;
374 }
375
376 private TypeVariable<?> getTypeVariable() {
377 return (TypeVariable)getType();
378 }
379
380 @Override
381 public boolean equals(Object o) {
382 if (o instanceof AnnotatedTypeVariable) {
383 AnnotatedTypeVariable that = (AnnotatedTypeVariable) o;
384 return equalsTypeAndAnnotations(that) &&
385 Arrays.equals(getAnnotatedBounds(), that.getAnnotatedBounds());
386 } else {
387 return false;
388 }
389 }
390
391 @Override
392 public int hashCode() {
393 return baseHashCode() ^
394 Objects.hash((Object[])getAnnotatedBounds());
395 }
396 }
397
398 private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl
399 implements AnnotatedParameterizedType {
400 AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
401 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
402 AnnotatedElement decl) {
403 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
404 }
405
406 @Override
407 public AnnotatedType[] getAnnotatedActualTypeArguments() {
408 Type[] arguments = getParameterizedType().getActualTypeArguments();
409 AnnotatedType[] res = new AnnotatedType[arguments.length];
410 Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
411 int initialCapacity = getTypeAnnotations().length;
412 for (int i = 0; i < res.length; i++) {
413 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
414 LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
415 for (TypeAnnotation t : getTypeAnnotations())
426
427 @Override
428 public AnnotatedType getAnnotatedOwnerType() {
429 Type owner = getParameterizedType().getOwnerType();
430 if (owner == null)
431 return null;
432 LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
433 TypeAnnotation[]all = getTypeAnnotations();
434 List<TypeAnnotation> l = new ArrayList<>(all.length);
435
436 for (TypeAnnotation t : all)
437 if (t.getLocationInfo().isSameLocationInfo(outerLoc))
438 l.add(t);
439
440 return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
441 }
442
443 private ParameterizedType getParameterizedType() {
444 return (ParameterizedType)getType();
445 }
446
447 @Override
448 public boolean equals(Object o) {
449 if (o instanceof AnnotatedParameterizedType) {
450 AnnotatedParameterizedType that = (AnnotatedParameterizedType) o;
451 return equalsTypeAndAnnotations(that) &&
452 Arrays.equals(getAnnotatedActualTypeArguments(), that.getAnnotatedActualTypeArguments());
453 } else {
454 return false;
455 }
456 }
457
458 @Override
459 public int hashCode() {
460 return baseHashCode() ^
461 Objects.hash((Object[])getAnnotatedActualTypeArguments());
462 }
463 }
464
465 private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
466 private final boolean hasUpperBounds;
467 AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
468 TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
469 AnnotatedElement decl) {
470 super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
471 hasUpperBounds = (type.getLowerBounds().length == 0);
472 }
473
474 @Override
475 public AnnotatedType[] getAnnotatedUpperBounds() {
476 if (!hasUpperBounds()) {
477 return new AnnotatedType[] { buildAnnotatedType(Object.class,
478 LocationInfo.BASE_LOCATION,
479 EMPTY_TYPE_ANNOTATION_ARRAY,
480 EMPTY_TYPE_ANNOTATION_ARRAY,
481 null)
482 };
504 LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
505 List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
506 for (TypeAnnotation t : getTypeAnnotations())
507 if (t.getLocationInfo().isSameLocationInfo(newLoc))
508 l.add(t);
509 res[i] = buildAnnotatedType(bounds[i],
510 newLoc,
511 l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
512 getTypeAnnotations(),
513 getDecl());
514 }
515 return res;
516 }
517
518 private WildcardType getWildcardType() {
519 return (WildcardType)getType();
520 }
521
522 private boolean hasUpperBounds() {
523 return hasUpperBounds;
524 }
525
526 @Override
527 public boolean equals(Object o) {
528 if (o instanceof AnnotatedWildcardType) {
529 AnnotatedWildcardType that = (AnnotatedWildcardType) o;
530 return equalsTypeAndAnnotations(that) &&
531 // Treats ordering as significant
532 Arrays.equals(getAnnotatedLowerBounds(), that.getAnnotatedLowerBounds()) &&
533 // Treats ordering as significant
534 Arrays.equals(getAnnotatedUpperBounds(), that.getAnnotatedUpperBounds());
535 } else {
536 return false;
537 }
538 }
539
540 @Override
541 public int hashCode() {
542 return baseHashCode() ^
543 Objects.hash((Object[])getAnnotatedLowerBounds()) ^
544 Objects.hash((Object[])getAnnotatedUpperBounds());
545 }
546 }
547 }
|