1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
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 package net.bytebuddy.description.annotation;
17
18 import net.bytebuddy.ClassFileVersion;
19 import net.bytebuddy.build.CachedReturnPlugin;
20 import net.bytebuddy.description.enumeration.EnumerationDescription;
21 import net.bytebuddy.description.method.MethodDescription;
22 import net.bytebuddy.description.type.TypeDefinition;
23 import net.bytebuddy.description.type.TypeDescription;
24
25 import java.lang.annotation.Annotation;
26 import java.lang.annotation.AnnotationTypeMismatchException;
27 import java.lang.annotation.IncompleteAnnotationException;
28 import java.lang.reflect.Array;
29 import java.lang.reflect.Method;
30 import java.util.*;
31
32 /**
33 * Representation of an unloaded annotation value where all values represent either:
34 * <ul>
35 * <li>Primitive values (as their wrappers), {@link String}s or arrays of primitive types or strings.</li>
36 * <li>A {@link TypeDescription} or an array of such a descriptions.</li>
37 * <li>An {@link EnumerationDescription} or an array of such a description.</li>
38 * <li>An {@link AnnotationDescription} or an array of such a description.</li>
39 * </ul>
40 * The represented values are not necessarily resolvable, i.e. can contain non-available types, unknown enumeration
41 * constants or inconsistent annotations.
42 *
43 * @param <T> The represented value's unloaded type.
44 * @param <S> The represented value's loaded type.
45 */
46 public interface AnnotationValue<T, S> {
47
48 /**
49 * An undefined annotation value.
50 */
51 AnnotationValue<?, ?> UNDEFINED = null;
52
53 /**
54 * Returns the state of the represented annotation value.
55 *
56 * @return The state represented by this instance.
57 */
58 State getState();
59
60 /**
61 * Filters this annotation value as a valid value of the provided property.
62 *
63 * @param property The property to filter against.
64 * @return This annotation value or a new annotation value that describes why this value is not a valid value for the supplied property.
65 */
66 AnnotationValue<T, S> filter(MethodDescription.InDefinedShape property);
67
68 /**
69 * Filters this annotation value as a valid value of the provided property.
70 *
71 * @param property The property to filter against.
72 * @param typeDefinition The expected type.
73 * @return This annotation value or a new annotation value that describes why this value is not a valid value for the supplied property.
74 */
75 AnnotationValue<T, S> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition);
76
77 /**
78 * Resolves the unloaded value of this annotation. The return value of this method is not defined if this annotation value is invalid.
79 *
80 * @return The unloaded value of this annotation.
81 */
82 T resolve();
83
84 /**
85 * Resolves the unloaded value of this annotation. The return value of this method is not defined if this annotation value is invalid.
86 *
87 * @param type The annotation value's unloaded type.
88 * @param <W> The annotation value's unloaded type.
89 * @return The unloaded value of this annotation.
90 */
91 <W> W resolve(Class<? extends W> type);
92
93 /**
94 * Returns the loaded value of this annotation.
95 *
96 * @param classLoader The class loader for loading this value.
97 * @return The loaded value of this annotation.
98 */
99 Loaded<S> load(ClassLoader classLoader);
100
101 /**
102 * A rendering dispatcher is responsible for resolving annotation values to {@link String} representations.
103 */
104 enum RenderingDispatcher {
105
106 /**
107 * A rendering dispatcher for any VM previous to Java 9.
108 */
109 LEGACY_VM('[', ']') {
110 @Override
111 public String toSourceString(char value) {
112 return Character.toString(value);
113 }
114
115 @Override
116 public String toSourceString(long value) {
117 return Long.toString(value);
118 }
119
120 @Override
121 public String toSourceString(float value) {
122 return Float.toString(value);
123 }
124
125 @Override
126 public String toSourceString(double value) {
127 return Double.toString(value);
128 }
129
130 @Override
131 public String toSourceString(String value) {
132 return value;
133 }
134
135 @Override
136 public String toSourceString(TypeDescription value) {
137 return value.toString();
138 }
139 },
140
141 /**
142 * A rendering dispatcher for Java 9 onward.
143 */
144 JAVA_9_CAPABLE_VM('{', '}') {
145 @Override
146 public String toSourceString(char value) {
147 StringBuilder stringBuilder = new StringBuilder().append('\'');
148 if (value == '\'') {
149 stringBuilder.append("\\\'");
150 } else {
151 stringBuilder.append(value);
152 }
153 return stringBuilder.append('\'').toString();
154 }
155
156 @Override
157 public String toSourceString(long value) {
158 return Math.abs(value) <= Integer.MAX_VALUE
159 ? String.valueOf(value)
160 : value + "L";
161 }
162
163 @Override
164 public String toSourceString(float value) {
165 return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
166 ? value + "f"
167 : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
168 }
169
170 @Override
171 public String toSourceString(double value) {
172 return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
173 ? Double.toString(value)
174 : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
175 }
176
177 @Override
178 public String toSourceString(String value) {
179 return "\"" + (value.indexOf('"') == -1
180 ? value
181 : value.replace("\"", "\\\"")) + "\"";
182 }
183
184 @Override
185 public String toSourceString(TypeDescription value) {
186 return value.getActualName() + ".class";
187 }
188 },
189
190 /**
191 * A rendering dispatcher for Java 14 onward.
192 */
193 JAVA_14_CAPABLE_VM('{', '}') {
194 @Override
195 public String toSourceString(byte value) {
196 return "(byte)0x" + Integer.toHexString(value);
197 }
198
199 @Override
200 public String toSourceString(char value) {
201 StringBuilder stringBuilder = new StringBuilder().append('\'');
202 if (value == '\'') {
203 stringBuilder.append("\\\'");
204 } else {
205 stringBuilder.append(value);
206 }
207 return stringBuilder.append('\'').toString();
208 }
209
210 @Override
211 public String toSourceString(long value) {
212 return value + "L";
213 }
214
215 @Override
216 public String toSourceString(float value) {
217 return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
218 ? value + "f"
219 : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
220 }
221
222 @Override
223 public String toSourceString(double value) {
224 return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
225 ? Double.toString(value)
226 : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
227 }
228
229 @Override
230 public String toSourceString(String value) {
231 return "\"" + (value.indexOf('"') == -1
232 ? value
233 : value.replace("\"", "\\\"")) + "\"";
234 }
235
236 @Override
237 public String toSourceString(TypeDescription value) {
238 return value.getActualName() + ".class";
239 }
240 };
241
242 /**
243 * The rendering dispatcher for the current VM.
244 */
245 public static final RenderingDispatcher CURRENT;
246
247 static {
248 ClassFileVersion classFileVersion = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6);
249 if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V14)) {
250 CURRENT = RenderingDispatcher.JAVA_14_CAPABLE_VM;
251 } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V9)) {
252 CURRENT = RenderingDispatcher.JAVA_9_CAPABLE_VM;
253 } else {
254 CURRENT = RenderingDispatcher.LEGACY_VM;
255 }
256 }
257
258 /**
259 * The opening brace of an array {@link String} representation.
260 */
261 private final char openingBrace;
262
263 /**
264 * The closing brace of an array {@link String} representation.
265 */
266 private final char closingBrace;
267
268 /**
269 * Creates a new rendering dispatcher.
270 *
271 * @param openingBrace The opening brace of an array {@link String} representation.
272 * @param closingBrace The closing brace of an array {@link String} representation.
273 */
274 RenderingDispatcher(char openingBrace, char closingBrace) {
275 this.openingBrace = openingBrace;
276 this.closingBrace = closingBrace;
277 }
278
279 /**
280 * Represents the supplied {@code boolean} value as a {@link String}.
281 *
282 * @param value The {@code boolean} value to render.
283 * @return An appropriate {@link String} representation.
284 */
285 public String toSourceString(boolean value) {
286 return Boolean.toString(value);
287 }
288
289 /**
290 * Represents the supplied {@code boolean} value as a {@link String}.
291 *
292 * @param value The {@code boolean} value to render.
293 * @return An appropriate {@link String} representation.
294 */
295 public String toSourceString(byte value) {
296 return Byte.toString(value);
297 }
298
299 /**
300 * Represents the supplied {@code short} value as a {@link String}.
301 *
302 * @param value The {@code short} value to render.
303 * @return An appropriate {@link String} representation.
304 */
305 public String toSourceString(short value) {
306 return Short.toString(value);
307 }
308
309 /**
310 * Represents the supplied {@code char} value as a {@link String}.
311 *
312 * @param value The {@code char} value to render.
313 * @return An appropriate {@link String} representation.
314 */
315 public abstract String toSourceString(char value);
316
317 /**
318 * Represents the supplied {@code int} value as a {@link String}.
319 *
320 * @param value The {@code int} value to render.
321 * @return An appropriate {@link String} representation.
322 */
323 public String toSourceString(int value) {
324 return Integer.toString(value);
325 }
326
327 /**
328 * Represents the supplied {@code long} value as a {@link String}.
329 *
330 * @param value The {@code long} value to render.
331 * @return An appropriate {@link String} representation.
332 */
333 public abstract String toSourceString(long value);
334
335 /**
336 * Represents the supplied {@code float} value as a {@link String}.
337 *
338 * @param value The {@code float} value to render.
339 * @return An appropriate {@link String} representation.
340 */
341 public abstract String toSourceString(float value);
342
343 /**
344 * Represents the supplied {@code double} value as a {@link String}.
345 *
346 * @param value The {@code double} value to render.
347 * @return An appropriate {@link String} representation.
348 */
349 public abstract String toSourceString(double value);
350
351 /**
352 * Represents the supplied {@link String} value as a {@link String}.
353 *
354 * @param value The {@link String} value to render.
355 * @return An appropriate {@link String} representation.
356 */
357 public abstract String toSourceString(String value);
358
359 /**
360 * Represents the supplied {@link TypeDescription} value as a {@link String}.
361 *
362 * @param value The {@link TypeDescription} value to render.
363 * @return An appropriate {@link String} representation.
364 */
365 public abstract String toSourceString(TypeDescription value);
366
367 /**
368 * Represents the supplied list elements as a {@link String}.
369 *
370 * @param values The elements to render where each element is represented by its {@link Object#toString()} representation.
371 * @return An appropriate {@link String} representation.
372 */
373 public String toSourceString(List<?> values) {
374 StringBuilder stringBuilder = new StringBuilder().append(openingBrace);
375 boolean first = true;
376 for (Object value : values) {
377 if (first) {
378 first = false;
379 } else {
380 stringBuilder.append(", ");
381 }
382 stringBuilder.append(value);
383 }
384 return stringBuilder.append(closingBrace).toString();
385 }
386
387 /**
388 * Resolves the supplied type description's component tag.
389 *
390 * @param typeDescription The type to resolve.
391 * @return The character that describes the component tag as an {@code int} to ease concatenation.
392 */
393 public int toComponentTag(TypeDescription typeDescription) {
394 if (typeDescription.represents(boolean.class)) {
395 return 'Z';
396 } else if (typeDescription.represents(byte.class)) {
397 return 'B';
398 } else if (typeDescription.represents(short.class)) {
399 return 'S';
400 } else if (typeDescription.represents(char.class)) {
401 return 'C';
402 } else if (typeDescription.represents(int.class)) {
403 return 'I';
404 } else if (typeDescription.represents(long.class)) {
405 return 'J';
406 } else if (typeDescription.represents(float.class)) {
407 return 'F';
408 } else if (typeDescription.represents(double.class)) {
409 return 'D';
410 } else if (typeDescription.represents(String.class)) {
411 return 's';
412 } else if (typeDescription.represents(Class.class)) {
413 return 'c';
414 } else if (typeDescription.isEnum()) {
415 return 'e';
416 } else if (typeDescription.isAnnotation()) {
417 return '@';
418 } else if (typeDescription.isArray()) {
419 return '[';
420 } else {
421 throw new IllegalArgumentException("Not an annotation component: " + typeDescription);
422 }
423 }
424 }
425
426 /**
427 * A loaded variant of an {@link AnnotationValue}. While
428 * implementations of this value are required to be processed successfully by a
429 * {@link java.lang.ClassLoader} they might still be unresolved. Typical errors on loading an annotation
430 * value are:
431 * <ul>
432 * <li>{@link java.lang.annotation.IncompleteAnnotationException}: An annotation does not define a value
433 * even though no default value for a property is provided.</li>
434 * <li>{@link java.lang.EnumConstantNotPresentException}: An annotation defines an unknown value for
435 * a known enumeration.</li>
436 * <li>{@link java.lang.annotation.AnnotationTypeMismatchException}: An annotation property is not
437 * of the expected type.</li>
438 * </ul>
439 * Implementations of this interface must implement methods for {@link Object#hashCode()} and
440 * {@link Object#toString()} that resemble those used for the annotation values of an actual
441 * {@link java.lang.annotation.Annotation} implementation. Also, instances must implement
442 * {@link java.lang.Object#equals(Object)} to return {@code true} for other instances of
443 * this interface that represent the same annotation value.
444 *
445 * @param <U> The represented value's type.
446 */
447 interface Loaded<U> {
448
449 /**
450 * Returns the state of the represented loaded annotation value.
451 *
452 * @return The state represented by this instance.
453 */
454 State getState();
455
456 /**
457 * Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
458 * exception if this value is either not defined or not resolved.
459 *
460 * @return The actual annotation value represented by this instance.
461 */
462 U resolve();
463
464 /**
465 * Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
466 * exception if this value is either not defined or not resolved.
467 *
468 * @param type The value's loaded type.
469 * @param <V> The value's loaded type.
470 * @return The actual annotation value represented by this instance.
471 */
472 <V> V resolve(Class<? extends V> type);
473
474 /**
475 * Verifies if this loaded value represents the supplied loaded value.
476 *
477 * @param value A loaded annotation value.
478 * @return {@code true} if the supplied annotation value is represented by this annotation value.
479 */
480 boolean represents(Object value);
481
482 /**
483 * An abstract base implementation of a loaded annotation value.
484 *
485 * @param <W> The represented loaded type.
486 */
487 abstract class AbstractBase<W> implements Loaded<W> {
488
489 /**
490 * {@inheritDoc}
491 */
492 public <X> X resolve(Class<? extends X> type) {
493 return type.cast(resolve());
494 }
495
496 /**
497 * A base implementation for an unresolved property.
498 *
499 * @param <Z> The represented loaded type.
500 */
501 public abstract static class ForUnresolvedProperty<Z> extends AbstractBase<Z> {
502
503 /**
504 * {@inheritDoc}
505 */
506 public State getState() {
507 return State.UNRESOLVED;
508 }
509
510 /**
511 * {@inheritDoc}
512 */
513 public boolean represents(Object value) {
514 return false;
515 }
516 }
517 }
518 }
519
520 /**
521 * Represents the state of a {@link Loaded} annotation property.
522 */
523 enum State {
524
525 /**
526 * An undefined annotation value describes an annotation property which is missing such that
527 * an {@link java.lang.annotation.IncompleteAnnotationException} would be thrown.
528 */
529 UNDEFINED,
530
531 /**
532 * An unresolved annotation value describes an annotation property which does not represent a
533 * valid value but an exceptional state.
534 */
535 UNRESOLVED,
536
537 /**
538 * A resolved annotation value describes an annotation property with an actual value.
539 */
540 RESOLVED;
541
542 /**
543 * Returns {@code true} if the related annotation value is defined, i.e. either represents
544 * an actual value or an exceptional state.
545 *
546 * @return {@code true} if the related annotation value is defined.
547 */
548 public boolean isDefined() {
549 return this != UNDEFINED;
550 }
551
552 /**
553 * Returns {@code true} if the related annotation value is resolved, i.e. represents an actual
554 * value.
555 *
556 * @return {@code true} if the related annotation value is resolved.
557 */
558 public boolean isResolved() {
559 return this == RESOLVED;
560 }
561 }
562
563 /**
564 * An abstract base implementation of an unloaded annotation value.
565 *
566 * @param <U> The represented unloaded type.
567 * @param <V> The represented loaded type.
568 */
569 abstract class AbstractBase<U, V> implements AnnotationValue<U, V> {
570
571 /**
572 * {@inheritDoc}
573 */
574 public <W> W resolve(Class<? extends W> type) {
575 return type.cast(resolve());
576 }
577
578 @Override
579 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property) {
580 return filter(property, property.getReturnType());
581 }
582 }
583
584 /**
585 * Represents a primitive value, a {@link java.lang.String} or an array of the latter types.
586 *
587 * @param <U> The type where primitive values are represented by their boxed type.
588 */
589 class ForConstant<U> extends AbstractBase<U, U> {
590
591 /**
592 * The represented value.
593 */
594 private final U value;
595
596 /**
597 * The property delegate for the value's type.
598 */
599 private final PropertyDelegate propertyDelegate;
600
601 /**
602 * Creates a new constant annotation value.
603 *
604 * @param value The represented value.
605 * @param propertyDelegate The property delegate for the value's type.
606 */
607 protected ForConstant(U value, PropertyDelegate propertyDelegate) {
608 this.value = value;
609 this.propertyDelegate = propertyDelegate;
610 }
611
612 /**
613 * Creates an annotation value for a {@code boolean} value.
614 *
615 * @param value The {@code boolean} value to represent.
616 * @return An appropriate annotation value.
617 */
618 public static AnnotationValue<Boolean, Boolean> of(boolean value) {
619 return new ForConstant<Boolean>(value, PropertyDelegate.ForNonArrayType.BOOLEAN);
620 }
621
622 /**
623 * Creates an annotation value for a {@code byte} value.
624 *
625 * @param value The {@code byte} value to represent.
626 * @return An appropriate annotation value.
627 */
628 public static AnnotationValue<Byte, Byte> of(byte value) {
629 return new ForConstant<Byte>(value, PropertyDelegate.ForNonArrayType.BYTE);
630 }
631
632 /**
633 * Creates an annotation value for a {@code short} value.
634 *
635 * @param value The {@code short} value to represent.
636 * @return An appropriate annotation value.
637 */
638 public static AnnotationValue<Short, Short> of(short value) {
639 return new ForConstant<Short>(value, PropertyDelegate.ForNonArrayType.SHORT);
640 }
641
642 /**
643 * Creates an annotation value for a {@code char} value.
644 *
645 * @param value The {@code char} value to represent.
646 * @return An appropriate annotation value.
647 */
648 public static AnnotationValue<Character, Character> of(char value) {
649 return new ForConstant<Character>(value, PropertyDelegate.ForNonArrayType.CHARACTER);
650 }
651
652 /**
653 * Creates an annotation value for a {@code int} value.
654 *
655 * @param value The {@code int} value to represent.
656 * @return An appropriate annotation value.
657 */
658 public static AnnotationValue<Integer, Integer> of(int value) {
659 return new ForConstant<Integer>(value, PropertyDelegate.ForNonArrayType.INTEGER);
660 }
661
662 /**
663 * Creates an annotation value for a {@code long} value.
664 *
665 * @param value The {@code long} value to represent.
666 * @return An appropriate annotation value.
667 */
668 public static AnnotationValue<Long, Long> of(long value) {
669 return new ForConstant<Long>(value, PropertyDelegate.ForNonArrayType.LONG);
670 }
671
672 /**
673 * Creates an annotation value for a {@code float} value.
674 *
675 * @param value The {@code float} value to represent.
676 * @return An appropriate annotation value.
677 */
678 public static AnnotationValue<Float, Float> of(float value) {
679 return new ForConstant<Float>(value, PropertyDelegate.ForNonArrayType.FLOAT);
680 }
681
682 /**
683 * Creates an annotation value for a {@code double} value.
684 *
685 * @param value The {@code double} value to represent.
686 * @return An appropriate annotation value.
687 */
688 public static AnnotationValue<Double, Double> of(double value) {
689 return new ForConstant<Double>(value, PropertyDelegate.ForNonArrayType.DOUBLE);
690 }
691
692 /**
693 * Creates an annotation value for a {@link String} value.
694 *
695 * @param value The {@link String} value to represent.
696 * @return An appropriate annotation value.
697 */
698 public static AnnotationValue<String, String> of(String value) {
699 return new ForConstant<String>(value, PropertyDelegate.ForNonArrayType.STRING);
700 }
701
702 /**
703 * Creates an annotation value for a {@code boolean[]} value.
704 *
705 * @param value The {@code boolean[]} value to represent.
706 * @return An appropriate annotation value.
707 */
708 public static AnnotationValue<boolean[], boolean[]> of(boolean... value) {
709 return new ForConstant<boolean[]>(value, PropertyDelegate.ForArrayType.BOOLEAN);
710 }
711
712 /**
713 * Creates an annotation value for a {@code byte[]} value.
714 *
715 * @param value The {@code byte[]} value to represent.
716 * @return An appropriate annotation value.
717 */
718 public static AnnotationValue<byte[], byte[]> of(byte... value) {
719 return new ForConstant<byte[]>(value, PropertyDelegate.ForArrayType.BYTE);
720 }
721
722 /**
723 * Creates an annotation value for a {@code short[]} value.
724 *
725 * @param value The {@code short[]} value to represent.
726 * @return An appropriate annotation value.
727 */
728 public static AnnotationValue<short[], short[]> of(short... value) {
729 return new ForConstant<short[]>(value, PropertyDelegate.ForArrayType.SHORT);
730 }
731
732 /**
733 * Creates an annotation value for a {@code char[]} value.
734 *
735 * @param value The {@code char[]} value to represent.
736 * @return An appropriate annotation value.
737 */
738 public static AnnotationValue<char[], char[]> of(char... value) {
739 return new ForConstant<char[]>(value, PropertyDelegate.ForArrayType.CHARACTER);
740 }
741
742 /**
743 * Creates an annotation value for a {@code int[]} value.
744 *
745 * @param value The {@code int[]} value to represent.
746 * @return An appropriate annotation value.
747 */
748 public static AnnotationValue<int[], int[]> of(int... value) {
749 return new ForConstant<int[]>(value, PropertyDelegate.ForArrayType.INTEGER);
750 }
751
752 /**
753 * Creates an annotation value for a {@code long[]} value.
754 *
755 * @param value The {@code long[]} value to represent.
756 * @return An appropriate annotation value.
757 */
758 public static AnnotationValue<long[], long[]> of(long... value) {
759 return new ForConstant<long[]>(value, PropertyDelegate.ForArrayType.LONG);
760 }
761
762 /**
763 * Creates an annotation value for a {@code float[]} value.
764 *
765 * @param value The {@code float[]} value to represent.
766 * @return An appropriate annotation value.
767 */
768 public static AnnotationValue<float[], float[]> of(float... value) {
769 return new ForConstant<float[]>(value, PropertyDelegate.ForArrayType.FLOAT);
770 }
771
772 /**
773 * Creates an annotation value for a {@code double[]} value.
774 *
775 * @param value The {@code double[]} value to represent.
776 * @return An appropriate annotation value.
777 */
778 public static AnnotationValue<double[], double[]> of(double... value) {
779 return new ForConstant<double[]>(value, PropertyDelegate.ForArrayType.DOUBLE);
780 }
781
782 /**
783 * Creates an annotation value for a {@code String[]} value.
784 *
785 * @param value The {@code String[]} value to represent.
786 * @return An appropriate annotation value.
787 */
788 public static AnnotationValue<String[], String[]> of(String... value) {
789 return new ForConstant<String[]>(value, PropertyDelegate.ForArrayType.STRING);
790 }
791
792 /**
793 * Creates an annotation value for any constant value, i.e any primitive (wrapper) type,
794 * any primitive array type or any {@link String} value or array. If no constant annotation
795 * type is provided, a runtime exception is thrown.
796 *
797 * @param value The value to represent.
798 * @return An appropriate annotation value.
799 */
800 public static AnnotationValue<?, ?> of(Object value) {
801 if (value instanceof Boolean) {
802 return of(((Boolean) value).booleanValue());
803 } else if (value instanceof Byte) {
804 return of(((Byte) value).byteValue());
805 } else if (value instanceof Short) {
806 return of(((Short) value).shortValue());
807 } else if (value instanceof Character) {
808 return of(((Character) value).charValue());
809 } else if (value instanceof Integer) {
810 return of(((Integer) value).intValue());
811 } else if (value instanceof Long) {
812 return of(((Long) value).longValue());
813 } else if (value instanceof Float) {
814 return of(((Float) value).floatValue());
815 } else if (value instanceof Double) {
816 return of(((Double) value).doubleValue());
817 } else if (value instanceof String) {
818 return of((String) value);
819 } else if (value instanceof boolean[]) {
820 return of((boolean[]) value);
821 } else if (value instanceof byte[]) {
822 return of((byte[]) value);
823 } else if (value instanceof short[]) {
824 return of((short[]) value);
825 } else if (value instanceof char[]) {
826 return of((char[]) value);
827 } else if (value instanceof int[]) {
828 return of((int[]) value);
829 } else if (value instanceof long[]) {
830 return of((long[]) value);
831 } else if (value instanceof float[]) {
832 return of((float[]) value);
833 } else if (value instanceof double[]) {
834 return of((double[]) value);
835 } else if (value instanceof String[]) {
836 return of((String[]) value);
837 } else {
838 throw new IllegalArgumentException("Not a constant annotation value: " + value);
839 }
840 }
841
842 /**
843 * {@inheritDoc}
844 */
845 public State getState() {
846 return State.RESOLVED;
847 }
848
849 /**
850 * {@inheritDoc}
851 */
852 public AnnotationValue<U, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
853 return typeDefinition.asErasure().asBoxed().represents(value.getClass()) ? this : new ForMismatchedType<U, U>(property, value.getClass().isArray()
854 ? "Array with component tag: " + RenderingDispatcher.CURRENT.toComponentTag(TypeDescription.ForLoadedType.of(value.getClass().getComponentType()))
855 : value.getClass().toString() + '[' + value + ']');
856 }
857
858 /**
859 * {@inheritDoc}
860 */
861 public U resolve() {
862 return value;
863 }
864
865 /**
866 * {@inheritDoc}
867 */
868 public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
869 return new Loaded<U>(value, propertyDelegate);
870 }
871
872 @Override
873 @CachedReturnPlugin.Enhance
874 public int hashCode() {
875 return propertyDelegate.hashCode(value);
876 }
877
878 @Override
879 public boolean equals(Object other) {
880 return this == other || other instanceof AnnotationValue<?, ?> && propertyDelegate.equals(value, ((AnnotationValue<?, ?>) other).resolve());
881 }
882
883 @Override
884 public String toString() {
885 return propertyDelegate.toString(value);
886 }
887
888 /**
889 * A property delegate for a constant annotation value.
890 */
891 protected interface PropertyDelegate {
892
893 /**
894 * Copies the provided value, if it is not immutable.
895 *
896 * @param value The value to copy.
897 * @param <S> The value's type.
898 * @return A copy of the provided instance or the provided value, if it is immutable.
899 */
900 <S> S copy(S value);
901
902 /**
903 * Computes the value's hash code.
904 *
905 * @param value The value for which to compute the hash code.
906 * @return The hash code of the provided value.
907 */
908 int hashCode(Object value);
909
910 /**
911 * Determines if another value is equal to a constant annotation value.
912 *
913 * @param self The value that is represented as a constant annotation value.
914 * @param other Any other value for which to determine equality.
915 * @return {@code true} if the provided value is equal to the represented value.
916 */
917 boolean equals(Object self, Object other);
918
919 /**
920 * Renders the supplied value as a {@link String}.
921 *
922 * @param value The value to render.
923 * @return An appropriate {@link String} representation of the provided value.
924 */
925 String toString(Object value);
926
927 /**
928 * A property delegate for a non-array type.
929 */
930 enum ForNonArrayType implements PropertyDelegate {
931
932 /**
933 * A property delegate for a {@code boolean} value.
934 */
935 BOOLEAN {
936 /** {@inheritDoc} */
937 public String toString(Object value) {
938 return RenderingDispatcher.CURRENT.toSourceString((Boolean) value);
939 }
940 },
941
942 /**
943 * A property delegate for a {@code byte} value.
944 */
945 BYTE {
946 /** {@inheritDoc} */
947 public String toString(Object value) {
948 return RenderingDispatcher.CURRENT.toSourceString((Byte) value);
949 }
950 },
951
952 /**
953 * A property delegate for a {@code short} value.
954 */
955 SHORT {
956 /** {@inheritDoc} */
957 public String toString(Object value) {
958 return RenderingDispatcher.CURRENT.toSourceString((Short) value);
959 }
960 },
961
962 /**
963 * A property delegate for a {@code char} value.
964 */
965 CHARACTER {
966 /** {@inheritDoc} */
967 public String toString(Object value) {
968 return RenderingDispatcher.CURRENT.toSourceString((Character) value);
969 }
970 },
971
972 /**
973 * A property delegate for a {@code int} value.
974 */
975 INTEGER {
976 /** {@inheritDoc} */
977 public String toString(Object value) {
978 return RenderingDispatcher.CURRENT.toSourceString((Integer) value);
979 }
980 },
981
982 /**
983 * A property delegate for a {@code long} value.
984 */
985 LONG {
986 /** {@inheritDoc} */
987 public String toString(Object value) {
988 return RenderingDispatcher.CURRENT.toSourceString((Long) value);
989 }
990 },
991
992 /**
993 * A property delegate for a {@code float} value.
994 */
995 FLOAT {
996 /** {@inheritDoc} */
997 public String toString(Object value) {
998 return RenderingDispatcher.CURRENT.toSourceString((Float) value);
999 }
1000 },
1001
1002 /**
1003 * A property delegate for a {@code double} value.
1004 */
1005 DOUBLE {
1006 /** {@inheritDoc} */
1007 public String toString(Object value) {
1008 return RenderingDispatcher.CURRENT.toSourceString((Double) value);
1009 }
1010 },
1011
1012 /**
1013 * A property delegate for a {@link String} value.
1014 */
1015 STRING {
1016 /** {@inheritDoc} */
1017 public String toString(Object value) {
1018 return RenderingDispatcher.CURRENT.toSourceString((String) value);
1019 }
1020 };
1021
1022 /**
1023 * {@inheritDoc}
1024 */
1025 public <S> S copy(S value) {
1026 return value;
1027 }
1028
1029 /**
1030 * {@inheritDoc}
1031 */
1032 public int hashCode(Object value) {
1033 return value.hashCode();
1034 }
1035
1036 /**
1037 * {@inheritDoc}
1038 */
1039 public boolean equals(Object self, Object other) {
1040 return self.equals(other);
1041 }
1042 }
1043
1044 /**
1045 * A property delegate for an array type of a constant value.
1046 */
1047 enum ForArrayType implements PropertyDelegate {
1048
1049 /**
1050 * A property delegate for a {@code boolean[]} value.
1051 */
1052 BOOLEAN {
1053 @Override
1054 protected Object doCopy(Object value) {
1055 return ((boolean[]) value).clone();
1056 }
1057
1058 /** {@inheritDoc} */
1059 public int hashCode(Object value) {
1060 return Arrays.hashCode((boolean[]) value);
1061 }
1062
1063 /** {@inheritDoc} */
1064 public boolean equals(Object self, Object other) {
1065 return other instanceof boolean[] && Arrays.equals((boolean[]) self, (boolean[]) other);
1066 }
1067
1068 @Override
1069 protected String toString(Object array, int index) {
1070 return ForNonArrayType.BOOLEAN.toString(Array.getBoolean(array, index));
1071 }
1072 },
1073
1074 /**
1075 * A property delegate for a {@code byte[]} value.
1076 */
1077 BYTE {
1078 @Override
1079 protected Object doCopy(Object value) {
1080 return ((byte[]) value).clone();
1081 }
1082
1083 /** {@inheritDoc} */
1084 public int hashCode(Object value) {
1085 return Arrays.hashCode((byte[]) value);
1086 }
1087
1088 /** {@inheritDoc} */
1089 public boolean equals(Object self, Object other) {
1090 return other instanceof byte[] && Arrays.equals((byte[]) self, (byte[]) other);
1091 }
1092
1093 @Override
1094 protected String toString(Object array, int index) {
1095 return ForNonArrayType.BYTE.toString(Array.getByte(array, index));
1096 }
1097 },
1098
1099 /**
1100 * A property delegate for a {@code short[]} value.
1101 */
1102 SHORT {
1103 @Override
1104 protected Object doCopy(Object value) {
1105 return ((short[]) value).clone();
1106 }
1107
1108 /** {@inheritDoc} */
1109 public int hashCode(Object value) {
1110 return Arrays.hashCode((short[]) value);
1111 }
1112
1113 /** {@inheritDoc} */
1114 public boolean equals(Object self, Object other) {
1115 return other instanceof short[] && Arrays.equals((short[]) self, (short[]) other);
1116 }
1117
1118 @Override
1119 protected String toString(Object array, int index) {
1120 return ForNonArrayType.SHORT.toString(Array.getShort(array, index));
1121 }
1122 },
1123
1124 /**
1125 * A property delegate for a {@code char[]} value.
1126 */
1127 CHARACTER {
1128 @Override
1129 protected Object doCopy(Object value) {
1130 return ((char[]) value).clone();
1131 }
1132
1133 /** {@inheritDoc} */
1134 public int hashCode(Object value) {
1135 return Arrays.hashCode((char[]) value);
1136 }
1137
1138 /** {@inheritDoc} */
1139 public boolean equals(Object self, Object other) {
1140 return other instanceof char[] && Arrays.equals((char[]) self, (char[]) other);
1141 }
1142
1143 @Override
1144 protected String toString(Object array, int index) {
1145 return ForNonArrayType.CHARACTER.toString(Array.getChar(array, index));
1146 }
1147 },
1148
1149 /**
1150 * A property delegate for a {@code int[]} value.
1151 */
1152 INTEGER {
1153 @Override
1154 protected Object doCopy(Object value) {
1155 return ((int[]) value).clone();
1156 }
1157
1158 /** {@inheritDoc} */
1159 public int hashCode(Object value) {
1160 return Arrays.hashCode((int[]) value);
1161 }
1162
1163 /** {@inheritDoc} */
1164 public boolean equals(Object self, Object other) {
1165 return other instanceof int[] && Arrays.equals((int[]) self, (int[]) other);
1166 }
1167
1168 @Override
1169 protected String toString(Object array, int index) {
1170 return ForNonArrayType.INTEGER.toString(Array.getInt(array, index));
1171 }
1172 },
1173
1174 /**
1175 * A property delegate for a {@code long[]} value.
1176 */
1177 LONG {
1178 @Override
1179 protected Object doCopy(Object value) {
1180 return ((long[]) value).clone();
1181 }
1182
1183 /** {@inheritDoc} */
1184 public int hashCode(Object value) {
1185 return Arrays.hashCode((long[]) value);
1186 }
1187
1188 /** {@inheritDoc} */
1189 public boolean equals(Object self, Object other) {
1190 return other instanceof long[] && Arrays.equals((long[]) self, (long[]) other);
1191 }
1192
1193 @Override
1194 protected String toString(Object array, int index) {
1195 return ForNonArrayType.LONG.toString(Array.getLong(array, index));
1196 }
1197 },
1198
1199 /**
1200 * A property delegate for a {@code float[]} value.
1201 */
1202 FLOAT {
1203 @Override
1204 protected Object doCopy(Object value) {
1205 return ((float[]) value).clone();
1206 }
1207
1208 /** {@inheritDoc} */
1209 public int hashCode(Object value) {
1210 return Arrays.hashCode((float[]) value);
1211 }
1212
1213 /** {@inheritDoc} */
1214 public boolean equals(Object self, Object other) {
1215 return other instanceof float[] && Arrays.equals((float[]) self, (float[]) other);
1216 }
1217
1218 @Override
1219 protected String toString(Object array, int index) {
1220 return ForNonArrayType.FLOAT.toString(Array.getFloat(array, index));
1221 }
1222 },
1223
1224 /**
1225 * A property delegate for a {@code double[]} value.
1226 */
1227 DOUBLE {
1228 @Override
1229 protected Object doCopy(Object value) {
1230 return ((double[]) value).clone();
1231 }
1232
1233 /** {@inheritDoc} */
1234 public int hashCode(Object value) {
1235 return Arrays.hashCode((double[]) value);
1236 }
1237
1238 /** {@inheritDoc} */
1239 public boolean equals(Object self, Object other) {
1240 return other instanceof double[] && Arrays.equals((double[]) self, (double[]) other);
1241 }
1242
1243 @Override
1244 protected String toString(Object array, int index) {
1245 return ForNonArrayType.DOUBLE.toString(Array.getDouble(array, index));
1246 }
1247 },
1248
1249 /**
1250 * A property delegate for a {@code String[]} value.
1251 */
1252 STRING {
1253 @Override
1254 protected Object doCopy(Object value) {
1255 return ((String[]) value).clone();
1256 }
1257
1258 /** {@inheritDoc} */
1259 public int hashCode(Object value) {
1260 return Arrays.hashCode((String[]) value);
1261 }
1262
1263 /** {@inheritDoc} */
1264 public boolean equals(Object self, Object other) {
1265 return other instanceof String[] && Arrays.equals((String[]) self, (String[]) other);
1266 }
1267
1268 @Override
1269 protected String toString(Object array, int index) {
1270 return ForNonArrayType.STRING.toString(Array.get(array, index));
1271 }
1272 };
1273
1274 /**
1275 * {@inheritDoc}
1276 */
1277 @SuppressWarnings("unchecked")
1278 public <S> S copy(S value) {
1279 return (S) doCopy(value);
1280 }
1281
1282 /**
1283 * Creates a copy of the provided array.
1284 *
1285 * @param value The array to copy.
1286 * @return A shallow copy of the provided array.
1287 */
1288 protected abstract Object doCopy(Object value);
1289
1290 /**
1291 * {@inheritDoc}
1292 */
1293 public String toString(Object value) {
1294 List<String> elements = new ArrayList<String>(Array.getLength(value));
1295 for (int index = 0; index < Array.getLength(value); index++) {
1296 elements.add(toString(value, index));
1297 }
1298 return RenderingDispatcher.CURRENT.toSourceString(elements);
1299 }
1300
1301 /**
1302 * Renders the array element at the specified index.
1303 *
1304 * @param array The array for which an element should be rendered.
1305 * @param index The index of the array element to render.
1306 * @return A {@link String} representation of the array element at the supplied index.
1307 */
1308 protected abstract String toString(Object array, int index);
1309 }
1310 }
1311
1312 /**
1313 * Represents a trivial loaded value.
1314 *
1315 * @param <V> The annotation properties type.
1316 */
1317 protected static class Loaded<V> extends AnnotationValue.Loaded.AbstractBase<V> {
1318
1319 /**
1320 * The represented value.
1321 */
1322 private final V value;
1323
1324 /**
1325 * The property delegate for the value's type.
1326 */
1327 private final PropertyDelegate propertyDelegate;
1328
1329 /**
1330 * Creates a new loaded representation of a constant value.
1331 *
1332 * @param value The represented value.
1333 * @param propertyDelegate The property delegate for the value's type.
1334 */
1335 protected Loaded(V value, PropertyDelegate propertyDelegate) {
1336 this.value = value;
1337 this.propertyDelegate = propertyDelegate;
1338 }
1339
1340 /**
1341 * {@inheritDoc}
1342 */
1343 public State getState() {
1344 return State.RESOLVED;
1345 }
1346
1347 /**
1348 * {@inheritDoc}
1349 */
1350 public V resolve() {
1351 return propertyDelegate.copy(value);
1352 }
1353
1354 /**
1355 * {@inheritDoc}
1356 */
1357 public boolean represents(Object value) {
1358 return propertyDelegate.equals(this.value, value);
1359 }
1360
1361 @Override
1362 @CachedReturnPlugin.Enhance
1363 public int hashCode() {
1364 return propertyDelegate.hashCode(value);
1365 }
1366
1367 @Override
1368 public boolean equals(Object other) {
1369 if (this == other) {
1370 return true;
1371 } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1372 return false;
1373 }
1374 AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1375 return annotationValue.getState().isResolved() && propertyDelegate.equals(value, annotationValue.resolve());
1376 }
1377
1378 @Override
1379 public String toString() {
1380 return propertyDelegate.toString(value);
1381 }
1382 }
1383 }
1384
1385 /**
1386 * A description of an {@link java.lang.annotation.Annotation} as a value of another annotation.
1387 *
1388 * @param <U> The type of the annotation.
1389 */
1390 class ForAnnotationDescription<U extends Annotation> extends AbstractBase<AnnotationDescription, U> {
1391
1392 /**
1393 * The annotation description that this value represents.
1394 */
1395 private final AnnotationDescription annotationDescription;
1396
1397 /**
1398 * Creates a new annotation value for a given annotation description.
1399 *
1400 * @param annotationDescription The annotation description that this value represents.
1401 */
1402 public ForAnnotationDescription(AnnotationDescription annotationDescription) {
1403 this.annotationDescription = annotationDescription;
1404 }
1405
1406 /**
1407 * Creates an annotation value instance for describing the given annotation type and values.
1408 *
1409 * @param annotationType The annotation type.
1410 * @param annotationValues The values of the annotation.
1411 * @param <V> The type of the annotation.
1412 * @return An annotation value representing the given annotation.
1413 */
1414 public static <V extends Annotation> AnnotationValue<AnnotationDescription, V> of(TypeDescription annotationType,
1415 Map<String, ? extends AnnotationValue<?, ?>> annotationValues) {
1416 return new ForAnnotationDescription<V>(new AnnotationDescription.Latent(annotationType, annotationValues));
1417 }
1418
1419 /**
1420 * {@inheritDoc}
1421 */
1422 public State getState() {
1423 return State.RESOLVED;
1424 }
1425
1426 /**
1427 * {@inheritDoc}
1428 */
1429 public AnnotationValue<AnnotationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1430 return typeDefinition.asErasure().equals(annotationDescription.getAnnotationType())
1431 ? this
1432 : new ForMismatchedType<AnnotationDescription, U>(property, annotationDescription.getAnnotationType().toString() + '[' + annotationDescription + ']');
1433 }
1434
1435 /**
1436 * {@inheritDoc}
1437 */
1438 public AnnotationDescription resolve() {
1439 return annotationDescription;
1440 }
1441
1442 /**
1443 * {@inheritDoc}
1444 */
1445 @SuppressWarnings("unchecked")
1446 public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
1447 try {
1448 return new Loaded<U>(annotationDescription
1449 .prepare((Class<U>) Class.forName(annotationDescription.getAnnotationType().getName(), false, classLoader))
1450 .load());
1451 } catch (ClassNotFoundException exception) {
1452 return new ForMissingType.Loaded<U>(annotationDescription.getAnnotationType().getName(), exception);
1453 }
1454 }
1455
1456 @Override
1457 public int hashCode() {
1458 return annotationDescription.hashCode();
1459 }
1460
1461 @Override
1462 public boolean equals(Object other) {
1463 return this == other || other instanceof AnnotationValue<?, ?> && annotationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1464 }
1465
1466 @Override
1467 public String toString() {
1468 return annotationDescription.toString();
1469 }
1470
1471 /**
1472 * A loaded version of the described annotation.
1473 *
1474 * @param <V> The annotation type.
1475 */
1476 public static class Loaded<V extends Annotation> extends AnnotationValue.Loaded.AbstractBase<V> {
1477
1478 /**
1479 * The loaded version of the represented annotation.
1480 */
1481 private final V annotation;
1482
1483 /**
1484 * Creates a representation of a loaded annotation.
1485 *
1486 * @param annotation The represented annotation.
1487 */
1488 public Loaded(V annotation) {
1489 this.annotation = annotation;
1490 }
1491
1492 /**
1493 * {@inheritDoc}
1494 */
1495 public State getState() {
1496 return State.RESOLVED;
1497 }
1498
1499 /**
1500 * {@inheritDoc}
1501 */
1502 public V resolve() {
1503 return annotation;
1504 }
1505
1506 /**
1507 * {@inheritDoc}
1508 */
1509 public boolean represents(Object value) {
1510 return annotation.equals(value);
1511 }
1512
1513 @Override
1514 public int hashCode() {
1515 return annotation.hashCode();
1516 }
1517
1518 @Override
1519 public boolean equals(Object other) {
1520 if (this == other) {
1521 return true;
1522 } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1523 return false;
1524 }
1525 AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1526 return annotationValue.getState().isResolved() && annotation.equals(annotationValue.resolve());
1527 }
1528
1529 @Override
1530 public String toString() {
1531 return annotation.toString();
1532 }
1533 }
1534 }
1535
1536 /**
1537 * A description of an {@link java.lang.Enum} as a value of an annotation.
1538 *
1539 * @param <U> The type of the enumeration.
1540 */
1541 class ForEnumerationDescription<U extends Enum<U>> extends AbstractBase<EnumerationDescription, U> {
1542
1543 /**
1544 * The enumeration that is represented.
1545 */
1546 private final EnumerationDescription enumerationDescription;
1547
1548 /**
1549 * Creates a new description of an annotation value for a given enumeration.
1550 *
1551 * @param enumerationDescription The enumeration that is to be represented.
1552 */
1553 public ForEnumerationDescription(EnumerationDescription enumerationDescription) {
1554 this.enumerationDescription = enumerationDescription;
1555 }
1556
1557 /**
1558 * Creates a new annotation value for the given enumeration description.
1559 *
1560 * @param value The value to represent.
1561 * @param <V> The type of the represented enumeration.
1562 * @return An annotation value that describes the given enumeration.
1563 */
1564 public static <V extends Enum<V>> AnnotationValue<EnumerationDescription, V> of(EnumerationDescription value) {
1565 return new ForEnumerationDescription<V>(value);
1566 }
1567
1568 /**
1569 * {@inheritDoc}
1570 */
1571 public EnumerationDescription resolve() {
1572 return enumerationDescription;
1573 }
1574
1575 /**
1576 * {@inheritDoc}
1577 */
1578 public State getState() {
1579 return State.RESOLVED;
1580 }
1581
1582 /**
1583 * {@inheritDoc}
1584 */
1585 public AnnotationValue<EnumerationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1586 return typeDefinition.asErasure().equals(enumerationDescription.getEnumerationType())
1587 ? this
1588 : new ForMismatchedType<EnumerationDescription, U>(property, enumerationDescription.getEnumerationType().toString() + '[' + enumerationDescription.getValue() + ']');
1589 }
1590
1591 /**
1592 * {@inheritDoc}
1593 */
1594 @SuppressWarnings("unchecked")
1595 public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
1596 try {
1597 return new Loaded<U>(enumerationDescription.load((Class<U>) Class.forName(enumerationDescription.getEnumerationType().getName(), false, classLoader)));
1598 } catch (ClassNotFoundException exception) {
1599 return new ForMissingType.Loaded<U>(enumerationDescription.getEnumerationType().getName(), exception);
1600 }
1601 }
1602
1603 @Override
1604 public int hashCode() {
1605 return enumerationDescription.hashCode();
1606 }
1607
1608 @Override
1609 public boolean equals(Object other) {
1610 return this == other || other instanceof AnnotationValue<?, ?> && enumerationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1611 }
1612
1613 @Override
1614 public String toString() {
1615 return enumerationDescription.toString();
1616 }
1617
1618 /**
1619 * A loaded representation of an enumeration value.
1620 *
1621 * @param <V> The type of the represented enumeration.
1622 */
1623 public static class Loaded<V extends Enum<V>> extends AnnotationValue.Loaded.AbstractBase<V> {
1624
1625 /**
1626 * The represented enumeration.
1627 */
1628 private final V enumeration;
1629
1630 /**
1631 * Creates a loaded version of an enumeration description.
1632 *
1633 * @param enumeration The represented enumeration.
1634 */
1635 public Loaded(V enumeration) {
1636 this.enumeration = enumeration;
1637 }
1638
1639 /**
1640 * {@inheritDoc}
1641 */
1642 public State getState() {
1643 return State.RESOLVED;
1644 }
1645
1646 /**
1647 * {@inheritDoc}
1648 */
1649 public V resolve() {
1650 return enumeration;
1651 }
1652
1653 /**
1654 * {@inheritDoc}
1655 */
1656 public boolean represents(Object value) {
1657 return enumeration.equals(value);
1658 }
1659
1660 @Override
1661 public int hashCode() {
1662 return enumeration.hashCode();
1663 }
1664
1665 @Override
1666 public boolean equals(Object other) {
1667 if (this == other) {
1668 return true;
1669 } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1670 return false;
1671 }
1672 AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1673 return annotationValue.getState().isResolved() && enumeration.equals(annotationValue.resolve());
1674 }
1675
1676 @Override
1677 public String toString() {
1678 return enumeration.toString();
1679 }
1680
1681 /**
1682 * <p>
1683 * Represents an annotation's enumeration value for a runtime type that is not an enumeration type.
1684 * </p>
1685 * <p>
1686 * <b>Note</b>: Neither of {@link Object#hashCode()}, {@link Object#toString()} and
1687 * {@link java.lang.Object#equals(Object)} are implemented specifically what resembles the way
1688 * such exceptional states are represented in the Open JDK's annotation implementations.
1689 * </p>
1690 */
1691 public static class WithIncompatibleRuntimeType extends AnnotationValue.Loaded.AbstractBase<Enum<?>> {
1692
1693 /**
1694 * The runtime type which is not an enumeration type.
1695 */
1696 private final Class<?> type;
1697
1698 /**
1699 * Creates a new representation for an incompatible runtime type.
1700 *
1701 * @param type The runtime type which is not an enumeration type.
1702 */
1703 public WithIncompatibleRuntimeType(Class<?> type) {
1704 this.type = type;
1705 }
1706
1707 /**
1708 * {@inheritDoc}
1709 */
1710 public State getState() {
1711 return State.UNRESOLVED;
1712 }
1713
1714 /**
1715 * {@inheritDoc}
1716 */
1717 public Enum<?> resolve() {
1718 throw new IncompatibleClassChangeError("Not an enumeration type: " + type.toString());
1719 }
1720
1721 /**
1722 * {@inheritDoc}
1723 */
1724 public boolean represents(Object value) {
1725 return false;
1726 }
1727
1728 /* hashCode, equals and toString are intentionally not implemented */
1729 }
1730 }
1731
1732 /**
1733 * Represents a property with an enumeration constant that is not defined by an enumeration type.
1734 *
1735 * @param <U> The enumerationl type.
1736 */
1737 public static class WithUnknownConstant<U extends Enum<U>> extends AbstractBase<EnumerationDescription, U> {
1738
1739 /**
1740 * A description of the enumeration type.
1741 */
1742 private final TypeDescription typeDescription;
1743
1744 /**
1745 * The enumeration constant value.
1746 */
1747 private final String value;
1748
1749 /**
1750 * Creates a property description for an enumeration value that does not exist for the enumeration type.
1751 *
1752 * @param typeDescription A description of the enumeration type.
1753 * @param value The enumeration constant value.
1754 */
1755 public WithUnknownConstant(TypeDescription typeDescription, String value) {
1756 this.typeDescription = typeDescription;
1757 this.value = value;
1758 }
1759
1760 /**
1761 * {@inheritDoc}
1762 */
1763 public State getState() {
1764 return State.UNRESOLVED;
1765 }
1766
1767 /**
1768 * {@inheritDoc}
1769 */
1770 public AnnotationValue<EnumerationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1771 return this;
1772 }
1773
1774 /**
1775 * {@inheritDoc}
1776 */
1777 public EnumerationDescription resolve() {
1778 throw new IllegalStateException(typeDescription + " does not declare enumeration constant " + value);
1779 }
1780
1781 /**
1782 * {@inheritDoc}
1783 */
1784 @SuppressWarnings("unchecked")
1785 public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
1786 try {
1787 // Type casting to Object is required for Java 6 compilability.
1788 return (AnnotationValue.Loaded<U>) (Object) new Loaded((Class<Enum<?>>) Class.forName(typeDescription.getName(), false, classLoader), value);
1789 } catch (ClassNotFoundException exception) {
1790 return new ForMissingType.Loaded<U>(typeDescription.getName(), exception);
1791 }
1792 }
1793
1794 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
1795
1796 @Override
1797 public String toString() {
1798 return value + " /* Warning: constant not present! */";
1799 }
1800
1801 /**
1802 * Represents a property with an enumeration constant that is not defined by an enumeration type.
1803 */
1804 public static class Loaded extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<Enum<?>> {
1805
1806 /**
1807 * The loaded enumeration type.
1808 */
1809 private final Class<? extends Enum<?>> enumType;
1810
1811 /**
1812 * The value for which no enumeration constant exists at runtime.
1813 */
1814 private final String value;
1815
1816 /**
1817 * Creates a new representation for an unknown enumeration constant of an annotation.
1818 *
1819 * @param enumType The loaded enumeration type.
1820 * @param value The value for which no enumeration constant exists at runtime.
1821 */
1822 public Loaded(Class<? extends Enum<?>> enumType, String value) {
1823 this.enumType = enumType;
1824 this.value = value;
1825 }
1826
1827 /**
1828 * {@inheritDoc}
1829 */
1830 public Enum<?> resolve() {
1831 throw new EnumConstantNotPresentException(enumType, value);
1832 }
1833
1834 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
1835
1836 @Override
1837 public String toString() {
1838 return value + " /* Warning: constant not present! */";
1839 }
1840 }
1841 }
1842 }
1843
1844 /**
1845 * A description of a {@link java.lang.Class} as a value of an annotation.
1846 *
1847 * @param <U> The type of the {@link java.lang.Class} that is described.
1848 */
1849 class ForTypeDescription<U extends Class<U>> extends AbstractBase<TypeDescription, U> {
1850
1851 /**
1852 * Indicates to a class loading process that class initializers are not required to be executed when loading a type.
1853 */
1854 private static final boolean NO_INITIALIZATION = false;
1855
1856 /**
1857 * A description of the represented type.
1858 */
1859 private final TypeDescription typeDescription;
1860
1861 /**
1862 * Creates a new annotation value that represents a type.
1863 *
1864 * @param typeDescription The represented type.
1865 */
1866 public ForTypeDescription(TypeDescription typeDescription) {
1867 this.typeDescription = typeDescription;
1868 }
1869
1870 /**
1871 * Creates an annotation value for representing the given type.
1872 *
1873 * @param typeDescription The type to represent.
1874 * @param <V> The represented type.
1875 * @return An annotation value that represents the given type.
1876 */
1877 public static <V extends Class<V>> AnnotationValue<TypeDescription, V> of(TypeDescription typeDescription) {
1878 return new ForTypeDescription<V>(typeDescription);
1879 }
1880
1881 /**
1882 * {@inheritDoc}
1883 */
1884 public State getState() {
1885 return State.RESOLVED;
1886 }
1887
1888 /**
1889 * {@inheritDoc}
1890 */
1891 public AnnotationValue<TypeDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1892 return typeDefinition.asErasure().represents(Class.class)
1893 ? this
1894 : new ForMismatchedType<TypeDescription, U>(property, Class.class.getName() + '[' + typeDescription.getName() + ']');
1895 }
1896
1897 /**
1898 * {@inheritDoc}
1899 */
1900 public TypeDescription resolve() {
1901 return typeDescription;
1902 }
1903
1904 /**
1905 * {@inheritDoc}
1906 */
1907 @SuppressWarnings("unchecked")
1908 public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
1909 try {
1910 return new Loaded<U>((U) Class.forName(typeDescription.getName(), NO_INITIALIZATION, classLoader));
1911 } catch (ClassNotFoundException exception) {
1912 return new ForMissingType.Loaded<U>(typeDescription.getName(), exception);
1913 }
1914 }
1915
1916 @Override
1917 public int hashCode() {
1918 return typeDescription.hashCode();
1919 }
1920
1921 @Override
1922 public boolean equals(Object other) {
1923 return this == other || other instanceof AnnotationValue<?, ?> && typeDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1924 }
1925
1926 @Override
1927 public String toString() {
1928 return RenderingDispatcher.CURRENT.toSourceString(typeDescription);
1929 }
1930
1931 /**
1932 * A loaded annotation value for a given type.
1933 *
1934 * @param <U> The represented type.
1935 */
1936 protected static class Loaded<U extends Class<U>> extends AnnotationValue.Loaded.AbstractBase<U> {
1937
1938 /**
1939 * The represented type.
1940 */
1941 private final U type;
1942
1943 /**
1944 * Creates a new loaded annotation value for a given type.
1945 *
1946 * @param type The represented type.
1947 */
1948 public Loaded(U type) {
1949 this.type = type;
1950 }
1951
1952 /**
1953 * {@inheritDoc}
1954 */
1955 public State getState() {
1956 return State.RESOLVED;
1957 }
1958
1959 /**
1960 * {@inheritDoc}
1961 */
1962 public U resolve() {
1963 return type;
1964 }
1965
1966 /**
1967 * {@inheritDoc}
1968 */
1969 public boolean represents(Object value) {
1970 return type.equals(value);
1971 }
1972
1973 @Override
1974 public int hashCode() {
1975 return type.hashCode();
1976 }
1977
1978 @Override
1979 public boolean equals(Object other) {
1980 if (this == other) {
1981 return true;
1982 } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1983 return false;
1984 }
1985 AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1986 return annotationValue.getState().isResolved() && type.equals(annotationValue.resolve());
1987 }
1988
1989 @Override
1990 public String toString() {
1991 return RenderingDispatcher.CURRENT.toSourceString(TypeDescription.ForLoadedType.of(type));
1992 }
1993 }
1994 }
1995
1996 /**
1997 * Describes a complex array that is the value of an annotation. Complex arrays are arrays that might trigger the loading
1998 * of user-defined types, i.e. {@link java.lang.Class}, {@link java.lang.annotation.Annotation} and {@link java.lang.Enum}
1999 * instances.
2000 *
2001 * @param <U> The component type of the annotation's value when it is not loaded.
2002 * @param <V> The component type of the annotation's value when it is loaded.
2003 */
2004 class ForDescriptionArray<U, V> extends AbstractBase<U[], V[]> {
2005
2006 /**
2007 * The component type for arrays containing unloaded versions of the annotation array's values.
2008 */
2009 private final Class<?> unloadedComponentType;
2010
2011 /**
2012 * A description of the component type when it is loaded.
2013 */
2014 private final TypeDescription componentType;
2015
2016 /**
2017 * A list of values of the array elements.
2018 */
2019 private final List<? extends AnnotationValue<?, ?>> values;
2020
2021 /**
2022 * Creates a new complex array.
2023 *
2024 * @param unloadedComponentType The component type for arrays containing unloaded versions of the annotation array's values.
2025 * @param componentType A description of the component type when it is loaded.
2026 * @param values A list of values of the array elements.
2027 */
2028 public ForDescriptionArray(Class<?> unloadedComponentType,
2029 TypeDescription componentType,
2030 List<? extends AnnotationValue<?, ?>> values) {
2031 this.unloadedComponentType = unloadedComponentType;
2032 this.componentType = componentType;
2033 this.values = values;
2034 }
2035
2036 /**
2037 * Creates a new complex array of enumeration descriptions.
2038 *
2039 * @param enumerationType A description of the type of the enumeration.
2040 * @param enumerationDescription An array of enumeration descriptions.
2041 * @param <W> The type of the enumeration.
2042 * @return A description of the array of enumeration values.
2043 */
2044 public static <W extends Enum<W>> AnnotationValue<EnumerationDescription[], W[]> of(TypeDescription enumerationType,
2045 EnumerationDescription[] enumerationDescription) {
2046 List<AnnotationValue<EnumerationDescription, W>> values = new ArrayList<AnnotationValue<EnumerationDescription, W>>(enumerationDescription.length);
2047 for (EnumerationDescription value : enumerationDescription) {
2048 if (!value.getEnumerationType().equals(enumerationType)) {
2049 throw new IllegalArgumentException(value + " is not of " + enumerationType);
2050 }
2051 values.add(ForEnumerationDescription.<W>of(value));
2052 }
2053 return new ForDescriptionArray<EnumerationDescription, W>(EnumerationDescription.class, enumerationType, values);
2054 }
2055
2056 /**
2057 * Creates a new complex array of annotation descriptions.
2058 *
2059 * @param annotationType A description of the type of the annotation.
2060 * @param annotationDescription An array of annotation descriptions.
2061 * @param <W> The type of the annotation.
2062 * @return A description of the array of enumeration values.
2063 */
2064 public static <W extends Annotation> AnnotationValue<AnnotationDescription[], W[]> of(TypeDescription annotationType,
2065 AnnotationDescription[] annotationDescription) {
2066 List<AnnotationValue<AnnotationDescription, W>> values = new ArrayList<AnnotationValue<AnnotationDescription, W>>(annotationDescription.length);
2067 for (AnnotationDescription value : annotationDescription) {
2068 if (!value.getAnnotationType().equals(annotationType)) {
2069 throw new IllegalArgumentException(value + " is not of " + annotationType);
2070 }
2071 values.add(new ForAnnotationDescription<W>(value));
2072 }
2073 return new ForDescriptionArray<AnnotationDescription, W>(AnnotationDescription.class, annotationType, values);
2074 }
2075
2076 /**
2077 * Creates a new complex array of annotation descriptions.
2078 *
2079 * @param typeDescription A description of the types contained in the array.
2080 * @return A description of the array of enumeration values.
2081 */
2082 @SuppressWarnings("unchecked")
2083 public static AnnotationValue<TypeDescription[], Class<?>[]> of(TypeDescription[] typeDescription) {
2084 List<AnnotationValue<TypeDescription, Class<?>>> values = new ArrayList<AnnotationValue<TypeDescription, Class<?>>>(typeDescription.length);
2085 for (TypeDescription value : typeDescription) {
2086 values.add((AnnotationValue) ForTypeDescription.<Class>of(value));
2087 }
2088 return new ForDescriptionArray<TypeDescription, Class<?>>(TypeDescription.class, TypeDescription.CLASS, values);
2089 }
2090
2091 /**
2092 * {@inheritDoc}
2093 */
2094 public State getState() {
2095 return State.RESOLVED;
2096 }
2097
2098 /**
2099 * {@inheritDoc}
2100 */
2101 @SuppressWarnings("unchecked")
2102 public AnnotationValue<U[], V[]> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2103 if (typeDefinition.isArray() && typeDefinition.getComponentType().asErasure().equals(componentType)) {
2104 for (AnnotationValue<?, ?> value : values) {
2105 value = value.filter(property, typeDefinition.getComponentType());
2106 if (value.getState() != State.RESOLVED) {
2107 return (AnnotationValue<U[], V[]>) value;
2108 }
2109 }
2110 return this;
2111 } else {
2112 return new ForMismatchedType<U[], V[]>(property, "Array with component tag: " + RenderingDispatcher.CURRENT.toComponentTag(componentType));
2113 }
2114 }
2115
2116 /**
2117 * {@inheritDoc}
2118 */
2119 public U[] resolve() {
2120 @SuppressWarnings("unchecked")
2121 U[] resolved = (U[]) Array.newInstance(unloadedComponentType, values.size());
2122 int index = 0;
2123 for (AnnotationValue<?, ?> value : values) {
2124 Array.set(resolved, index++, value.resolve());
2125 }
2126 return resolved;
2127 }
2128
2129 /**
2130 * {@inheritDoc}
2131 */
2132 @SuppressWarnings("unchecked")
2133 public AnnotationValue.Loaded<V[]> load(ClassLoader classLoader) {
2134 List<AnnotationValue.Loaded<?>> values = new ArrayList<AnnotationValue.Loaded<?>>(this.values.size());
2135 for (AnnotationValue<?, ?> value : this.values) {
2136 values.add(value.load(classLoader));
2137 }
2138 try {
2139 return new Loaded<V>((Class<V>) Class.forName(componentType.getName(), false, classLoader), values);
2140 } catch (ClassNotFoundException exception) {
2141 return new ForMissingType.Loaded<V[]>(componentType.getName(), exception);
2142 }
2143 }
2144
2145 @Override
2146 @CachedReturnPlugin.Enhance
2147 public int hashCode() {
2148 int result = 1;
2149 for (AnnotationValue<?, ?> value : values) {
2150 result = 31 * result + value.hashCode();
2151 }
2152 return result;
2153 }
2154
2155 @Override
2156 public boolean equals(Object other) {
2157 if (this == other) {
2158 return true;
2159 } else if (!(other instanceof AnnotationValue<?, ?>)) {
2160 return false;
2161 }
2162 AnnotationValue<?, ?> annotationValue = (AnnotationValue<?, ?>) other;
2163 Object value = annotationValue.resolve();
2164 if (!(value instanceof Object[])) {
2165 return false;
2166 }
2167 Object[] arrayValue = (Object[]) value;
2168 if (values.size() != arrayValue.length) {
2169 return false;
2170 }
2171 Iterator<? extends AnnotationValue<?, ?>> iterator = values.iterator();
2172 for (Object aValue : arrayValue) {
2173 AnnotationValue<?, ?> self = iterator.next();
2174 if (!self.resolve().equals(aValue)) {
2175 return false;
2176 }
2177 }
2178 return true;
2179 }
2180
2181 @Override
2182 public String toString() {
2183 return RenderingDispatcher.CURRENT.toSourceString(values);
2184 }
2185
2186 /**
2187 * Represents a loaded complex array.
2188 *
2189 * @param <W> The component type of the loaded array.
2190 */
2191 protected static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase<W[]> {
2192
2193 /**
2194 * The loaded component type of the array.
2195 */
2196 private final Class<W> componentType;
2197
2198 /**
2199 * A list of loaded values that the represented array contains.
2200 */
2201 private final List<AnnotationValue.Loaded<?>> values;
2202
2203 /**
2204 * Creates a new loaded value representing a complex array.
2205 *
2206 * @param componentType The loaded component type of the array.
2207 * @param values A list of loaded values that the represented array contains.
2208 */
2209 protected Loaded(Class<W> componentType, List<AnnotationValue.Loaded<?>> values) {
2210 this.componentType = componentType;
2211 this.values = values;
2212 }
2213
2214 /**
2215 * {@inheritDoc}
2216 */
2217 public State getState() {
2218 for (AnnotationValue.Loaded<?> value : values) {
2219 if (!value.getState().isResolved()) {
2220 return State.UNRESOLVED;
2221 }
2222 }
2223 return State.RESOLVED;
2224 }
2225
2226 /**
2227 * {@inheritDoc}
2228 */
2229 public W[] resolve() {
2230 @SuppressWarnings("unchecked")
2231 W[] array = (W[]) Array.newInstance(componentType, values.size());
2232 int index = 0;
2233 for (AnnotationValue.Loaded<?> annotationValue : values) {
2234 Array.set(array, index++, annotationValue.resolve());
2235 }
2236 return array;
2237 }
2238
2239 /**
2240 * {@inheritDoc}
2241 */
2242 public boolean represents(Object value) {
2243 if (!(value instanceof Object[])) return false;
2244 if (value.getClass().getComponentType() != componentType) return false;
2245 Object[] array = (Object[]) value;
2246 if (values.size() != array.length) return false;
2247 Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
2248 for (Object aValue : array) {
2249 AnnotationValue.Loaded<?> self = iterator.next();
2250 if (!self.represents(aValue)) {
2251 return false;
2252 }
2253 }
2254 return true;
2255 }
2256
2257 @Override
2258 @CachedReturnPlugin.Enhance
2259 public int hashCode() {
2260 int result = 1;
2261 for (AnnotationValue.Loaded<?> value : values) {
2262 result = 31 * result + value.hashCode();
2263 }
2264 return result;
2265 }
2266
2267 @Override
2268 public boolean equals(Object other) {
2269 if (this == other) {
2270 return true;
2271 } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
2272 return false;
2273 }
2274 AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
2275 if (!annotationValue.getState().isResolved()) {
2276 return false;
2277 }
2278 Object value = annotationValue.resolve();
2279 if (!(value instanceof Object[])) {
2280 return false;
2281 }
2282 Object[] arrayValue = (Object[]) value;
2283 if (values.size() != arrayValue.length) {
2284 return false;
2285 }
2286 Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
2287 for (Object aValue : arrayValue) {
2288 AnnotationValue.Loaded<?> self = iterator.next();
2289 if (!self.getState().isResolved() || !self.resolve().equals(aValue)) {
2290 return false;
2291 }
2292 }
2293 return true;
2294 }
2295
2296 @Override
2297 public String toString() {
2298 return RenderingDispatcher.CURRENT.toSourceString(values);
2299 }
2300 }
2301 }
2302
2303 /**
2304 * An annotation value for a type that could not be loaded.
2305 *
2306 * @param <U> The type of the annotation's value when it is not loaded.
2307 * @param <V> The type of the annotation's value when it is loaded.
2308 */
2309 class ForMissingType<U, V> extends AbstractBase<U, V> {
2310
2311 /**
2312 * The type's binary name.
2313 */
2314 private final String typeName;
2315
2316 /**
2317 * Creates a new annotation value for a type that cannot be loaded.
2318 *
2319 * @param typeName The type's binary name.
2320 */
2321 public ForMissingType(String typeName) {
2322 this.typeName = typeName;
2323 }
2324
2325 /**
2326 * {@inheritDoc}
2327 */
2328 public State getState() {
2329 return State.UNRESOLVED;
2330 }
2331
2332 /**
2333 * {@inheritDoc}
2334 */
2335 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2336 return this;
2337 }
2338
2339 /**
2340 * {@inheritDoc}
2341 */
2342 public U resolve() {
2343 throw new IllegalStateException("Type not found: " + typeName);
2344 }
2345
2346 /**
2347 * {@inheritDoc}
2348 */
2349 public AnnotationValue.Loaded<V> load(ClassLoader classLoader) {
2350 return new Loaded<V>(typeName, new ClassNotFoundException(typeName));
2351 }
2352
2353 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2354
2355 @Override
2356 public String toString() {
2357 return typeName + ".class /* Warning: type not present! */";
2358 }
2359
2360 /**
2361 * Represents a missing type during an annotation's resolution.
2362 *
2363 * @param <U> The represented type.
2364 */
2365 public static class Loaded<U> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<U> {
2366
2367 /**
2368 * The type's binary name.
2369 */
2370 private final String typeName;
2371
2372 /**
2373 * The exception describing the missing type.
2374 */
2375 private final ClassNotFoundException exception;
2376
2377 /**
2378 * The type's binary name.
2379 *
2380 * @param typeName The type's binary name.
2381 * @param exception The exception describing the missing type.
2382 */
2383 public Loaded(String typeName, ClassNotFoundException exception) {
2384 this.typeName = typeName;
2385 this.exception = exception;
2386 }
2387
2388 /**
2389 * {@inheritDoc}
2390 */
2391 public U resolve() {
2392 throw new TypeNotPresentException(typeName, exception);
2393 }
2394
2395 @Override
2396 public String toString() {
2397 return typeName + ".class /* Warning: type not present! */";
2398 }
2399 }
2400 }
2401
2402 /**
2403 * Describes an annotation value that does not match the annotation' type for a property.
2404 *
2405 * @param <U> The type of the annotation's value when it is not loaded.
2406 * @param <V> The type of the annotation's value when it is loaded.
2407 */
2408 class ForMismatchedType<U, V> extends AbstractBase<U, V> {
2409
2410 /**
2411 * The property that does not defines a non-matching value.
2412 */
2413 private final MethodDescription.InDefinedShape property;
2414
2415 /**
2416 * A value description of the property.
2417 */
2418 private final String value;
2419
2420 /**
2421 * Creates an annotation description for a mismatched typeName.
2422 *
2423 * @param property The property that does not defines a non-matching value.
2424 * @param value A value description of the property.
2425 */
2426 public ForMismatchedType(MethodDescription.InDefinedShape property, String value) {
2427 this.property = property;
2428 this.value = value;
2429 }
2430
2431 /**
2432 * {@inheritDoc}
2433 */
2434 public State getState() {
2435 return State.UNRESOLVED;
2436 }
2437
2438 /**
2439 * {@inheritDoc}
2440 */
2441 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2442 return this;
2443 }
2444
2445 /**
2446 * {@inheritDoc}
2447 */
2448 public U resolve() {
2449 throw new IllegalStateException(property + " cannot define " + value);
2450 }
2451
2452 /**
2453 * {@inheritDoc}
2454 */
2455 public AnnotationValue.Loaded<V> load(ClassLoader classLoader) {
2456 try {
2457 Class<?> type = Class.forName(property.getDeclaringType().getName(), false, classLoader);
2458 try {
2459 return new Loaded<V>(type.getMethod(property.getName()), value);
2460 } catch (NoSuchMethodException exception) {
2461 return new ForIncompatibleType.Loaded<V>(type);
2462 }
2463 } catch (ClassNotFoundException exception) {
2464 return new ForMissingType.Loaded<V>(property.getDeclaringType().getName(), exception);
2465 }
2466 }
2467
2468 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2469
2470 @Override
2471 public String toString() {
2472 return "/* Warning type mismatch! \"" + value + "\" */";
2473 }
2474
2475 /**
2476 * Describes an annotation value for a property that is not assignable to it.
2477 *
2478 * @param <W> The type of the annotation's expected value.
2479 */
2480 public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<W> {
2481
2482 /**
2483 * The annotation property that is not well-defined.
2484 */
2485 private final Method property;
2486
2487 /**
2488 * A value description of the incompatible property or {@code null}.
2489 */
2490 private final String value;
2491
2492 /**
2493 * Creates a new loaded version of a property with an incompatible type.
2494 *
2495 * @param property The annotation property that is not well-defined.
2496 * @param value A value description of the incompatible property or {@code null}.
2497 */
2498 public Loaded(Method property, String value) {
2499 this.property = property;
2500 this.value = value;
2501 }
2502
2503 /**
2504 * {@inheritDoc}
2505 */
2506 public W resolve() {
2507 throw new AnnotationTypeMismatchException(property, value);
2508 }
2509 }
2510 }
2511
2512 /**
2513 * Represents a missing annotation property which is not represented by a default value.
2514 *
2515 * @param <U> The type of the annotation's value when it is not loaded.
2516 * @param <V> The type of the annotation's value when it is loaded.
2517 */
2518 class ForMissingValue<U, V> extends AnnotationValue.AbstractBase<U, V> {
2519
2520 /**
2521 * The annotation type for which a property is not defined.
2522 */
2523 private final TypeDescription typeDescription;
2524
2525 /**
2526 * The name of the property without an annotation value.
2527 */
2528 private final String property;
2529
2530 /**
2531 * Creates a new missing annotation value.
2532 *
2533 * @param typeDescription The annotation type for which a property is not defined.
2534 * @param property The name of the property without an annotation value.
2535 */
2536 public ForMissingValue(TypeDescription typeDescription, String property) {
2537 this.typeDescription = typeDescription;
2538 this.property = property;
2539 }
2540
2541 /**
2542 * {@inheritDoc}
2543 */
2544 public State getState() {
2545 return State.UNDEFINED;
2546 }
2547
2548 /**
2549 * {@inheritDoc}
2550 */
2551 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2552 return this;
2553 }
2554
2555 /**
2556 * {@inheritDoc}
2557 */
2558 @SuppressWarnings("unchecked")
2559 public AnnotationValue.Loaded<V> load(ClassLoader classLoader) {
2560 try {
2561 Class<? extends Annotation> type = (Class<? extends Annotation>) Class.forName(typeDescription.getName(), false, classLoader);
2562 return type.isAnnotation()
2563 ? new Loaded<V>(type, property)
2564 : new ForIncompatibleType.Loaded<V>(type);
2565 } catch (ClassNotFoundException exception) {
2566 return new ForMissingType.Loaded<V>(typeDescription.getName(), exception);
2567 }
2568 }
2569
2570 /**
2571 * {@inheritDoc}
2572 */
2573 public U resolve() {
2574 throw new IllegalStateException(typeDescription + " does not define " + property);
2575 }
2576
2577 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2578
2579 /**
2580 * Describes an annotation value for a property that is not assignable to it.
2581 *
2582 * @param <W> The type of the annotation's expected value.
2583 */
2584 public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase<W> {
2585
2586 /**
2587 * The annotation type.
2588 */
2589 private final Class<? extends Annotation> type;
2590
2591 /**
2592 * The name of the property for which the annotation value is missing.
2593 */
2594 private final String property;
2595
2596 /**
2597 * Creates a new loaded representation for an unresolved property.
2598 *
2599 * @param type The annotation type.
2600 * @param property The name of the property for which the annotation value is missing.
2601 */
2602 public Loaded(Class<? extends Annotation> type, String property) {
2603 this.type = type;
2604 this.property = property;
2605 }
2606
2607 /**
2608 * {@inheritDoc}
2609 */
2610 public State getState() {
2611 return State.UNDEFINED;
2612 }
2613
2614 /**
2615 * {@inheritDoc}
2616 */
2617 public W resolve() {
2618 throw new IncompleteAnnotationException(type, property);
2619 }
2620
2621 /**
2622 * {@inheritDoc}
2623 */
2624 public boolean represents(Object value) {
2625 return false;
2626 }
2627
2628 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2629 }
2630 }
2631
2632 /**
2633 * Represents an annotation value where its declared type does not fulfil an expectation.
2634 *
2635 * @param <U> The type of the annotation's value when it is not loaded.
2636 * @param <V> The type of the annotation's value when it is loaded.
2637 */
2638 class ForIncompatibleType<U, V> extends AnnotationValue.AbstractBase<U, V> {
2639
2640 /**
2641 * A description of the type that does not fulfil an expectation.
2642 */
2643 private final TypeDescription typeDescription;
2644
2645 /**
2646 * Creates a new description for an annotation value that does not fulfil expectations.
2647 *
2648 * @param typeDescription A description of the type that does not fulfil the expectations.
2649 */
2650 public ForIncompatibleType(TypeDescription typeDescription) {
2651 this.typeDescription = typeDescription;
2652 }
2653
2654 /**
2655 * {@inheritDoc}
2656 */
2657 public State getState() {
2658 return State.UNRESOLVED;
2659 }
2660
2661 /**
2662 * {@inheritDoc}
2663 */
2664 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2665 return this;
2666 }
2667
2668 /**
2669 * {@inheritDoc}
2670 */
2671 public U resolve() {
2672 throw new IllegalStateException("Property is defined with an incompatible runtime type: " + typeDescription);
2673 }
2674
2675 /**
2676 * {@inheritDoc}
2677 */
2678 public AnnotationValue.Loaded<V> load(ClassLoader classLoader) {
2679 try {
2680 return new Loaded<V>(Class.forName(typeDescription.getName(), false, classLoader));
2681 } catch (ClassNotFoundException exception) {
2682 return new ForMissingType.Loaded<V>(typeDescription.getName(), exception);
2683 }
2684 }
2685
2686 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2687
2688 @Override
2689 public String toString() {
2690 return "/* Warning type incompatibility! \"" + typeDescription.getName() + "\" */";
2691 }
2692
2693 /**
2694 * A description of annotation value for a type that does not fulfil an expectation.
2695 *
2696 * @param <W> The type of the annotation's expected value.
2697 */
2698 public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<W> {
2699
2700 /**
2701 * The type that does not fulfil an expectation.
2702 */
2703 private final Class<?> type;
2704
2705 /**
2706 * Creates a new description of an annotation.
2707 *
2708 * @param type The type that does not fulfil an expectation.
2709 */
2710 public Loaded(Class<?> type) {
2711 this.type = type;
2712 }
2713
2714 /**
2715 * {@inheritDoc}
2716 */
2717 public W resolve() {
2718 throw new IncompatibleClassChangeError(type.toString());
2719 }
2720
2721 /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2722
2723 @Override
2724 public String toString() {
2725 return "/* Warning type incompatibility! \"" + type.getName() + "\" */";
2726 }
2727 }
2728 }
2729 }
2730