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 truefor 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 trueif 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 trueif the related annotation value is defined, i.e. either represents
544          * an actual value or an exceptional state.
545          *
546          * @return {@code trueif the related annotation value is defined.
547          */

548         public boolean isDefined() {
549             return this != UNDEFINED;
550         }
551
552         /**
553          * Returns {@code trueif the related annotation value is resolved, i.e. represents an actual
554          * value.
555          *
556          * @return {@code trueif 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 trueif 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