• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #801

27 Oct 2025 09:37AM UTC coverage: 84.715% (-0.4%) from 85.118%
#801

push

raphw
Fix imports.

29586 of 34924 relevant lines covered (84.72%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.63
/byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationValue.java
1
/*
2
 * Copyright 2014 - Present 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.ClassFileVersion;
20
import net.bytebuddy.build.CachedReturnPlugin;
21
import net.bytebuddy.description.enumeration.EnumerationDescription;
22
import net.bytebuddy.description.method.MethodDescription;
23
import net.bytebuddy.description.type.TypeDefinition;
24
import net.bytebuddy.description.type.TypeDescription;
25
import net.bytebuddy.utility.nullability.AlwaysNull;
26
import net.bytebuddy.utility.nullability.MaybeNull;
27

28
import java.lang.annotation.Annotation;
29
import java.lang.annotation.AnnotationTypeMismatchException;
30
import java.lang.annotation.IncompleteAnnotationException;
31
import java.lang.reflect.Array;
32
import java.lang.reflect.Method;
33
import java.util.ArrayList;
34
import java.util.Arrays;
35
import java.util.HashMap;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Map;
39

40
/**
41
 * Representation of an unloaded annotation value where all values represent either:
42
 * <ul>
43
 * <li>Primitive values (as their wrappers), {@link String}s or arrays of primitive types or strings.</li>
44
 * <li>A {@link TypeDescription} or an array of such a descriptions.</li>
45
 * <li>An {@link EnumerationDescription} or an array of such a description.</li>
46
 * <li>An {@link AnnotationDescription} or an array of such a description.</li>
47
 * </ul>
48
 * The represented values are not necessarily resolvable, i.e. can contain non-available types, unknown enumeration
49
 * constants or inconsistent annotations.
50
 *
51
 * @param <T> The represented value's unloaded type.
52
 * @param <S> The represented value's  loaded type.
53
 */
54
public interface AnnotationValue<T, S> {
55

56
    /**
57
     * An undefined annotation value.
58
     */
59
    @AlwaysNull
60
    AnnotationValue<?, ?> UNDEFINED = null;
1✔
61

62
    /**
63
     * Returns the state of the represented annotation value.
64
     *
65
     * @return The state represented by this instance.
66
     */
67
    State getState();
68

69
    /**
70
     * Returns the property type of the annotation value.
71
     *
72
     * @return The property type of the annotation value.
73
     */
74
    Sort getSort();
75

76
    /**
77
     * Filters this annotation value as a valid value of the provided property.
78
     *
79
     * @param property The property to filter against.
80
     * @return This annotation value or a new annotation value that describes why this value is not a valid value for the supplied property.
81
     */
82
    AnnotationValue<T, S> filter(MethodDescription.InDefinedShape property);
83

84
    /**
85
     * Filters this annotation value as a valid value of the provided property.
86
     *
87
     * @param property       The property to filter against.
88
     * @param typeDefinition The expected type.
89
     * @return This annotation value or a new annotation value that describes why this value is not a valid value for the supplied property.
90
     */
91
    AnnotationValue<T, S> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition);
92

93
    /**
94
     * Resolves the unloaded value of this annotation. The return value of this method is not defined if this annotation value is invalid.
95
     *
96
     * @return The unloaded value of this annotation.
97
     */
98
    T resolve();
99

100
    /**
101
     * Resolves the unloaded value of this annotation. The return value of this method is not defined if this annotation value is invalid.
102
     *
103
     * @param type The annotation value's unloaded type.
104
     * @param <W>  The annotation value's unloaded type.
105
     * @return The unloaded value of this annotation.
106
     */
107
    <W> W resolve(Class<? extends W> type);
108

109
    /**
110
     * Returns the loaded value of this annotation.
111
     *
112
     * @param classLoader The class loader for loading this value or {@code null} for using the boot loader.
113
     * @return The loaded value of this annotation.
114
     */
115
    Loaded<S> load(@MaybeNull ClassLoader classLoader);
116

117
    /**
118
     * A rendering dispatcher is responsible for resolving annotation values to {@link String} representations.
119
     */
120
    enum RenderingDispatcher {
1✔
121

122
        /**
123
         * A rendering dispatcher for any VM previous to Java 9.
124
         */
125
        LEGACY_VM('[', ']', true) {
1✔
126
            @Override
127
            public String toSourceString(char value) {
128
                return Character.toString(value);
1✔
129
            }
130

131
            @Override
132
            public String toSourceString(long value) {
133
                return Long.toString(value);
1✔
134
            }
135

136
            @Override
137
            public String toSourceString(float value) {
138
                return Float.toString(value);
1✔
139
            }
140

141
            @Override
142
            public String toSourceString(double value) {
143
                return Double.toString(value);
1✔
144
            }
145

146
            @Override
147
            public String toSourceString(String value) {
148
                return value;
1✔
149
            }
150

151
            @Override
152
            public String toSourceString(TypeDescription value) {
153
                return value.toString();
1✔
154
            }
155
        },
156

157
        /**
158
         * A rendering dispatcher for Java 9 onward.
159
         */
160
        JAVA_9_CAPABLE_VM('{', '}', true) {
1✔
161
            @Override
162
            public String toSourceString(char value) {
163
                StringBuilder stringBuilder = new StringBuilder().append('\'');
1✔
164
                if (value == '\'') {
1✔
165
                    stringBuilder.append("\\'");
1✔
166
                } else {
167
                    stringBuilder.append(value);
1✔
168
                }
169
                return stringBuilder.append('\'').toString();
1✔
170
            }
171

172
            @Override
173
            public String toSourceString(long value) {
174
                return Math.abs(value) <= Integer.MAX_VALUE
1✔
175
                        ? String.valueOf(value)
1✔
176
                        : value + "L";
177
            }
178

179
            @Override
180
            public String toSourceString(float value) {
181
                return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
1✔
182
                        ? value + "f"
183
                        : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
1✔
184
            }
185

186
            @Override
187
            public String toSourceString(double value) {
188
                return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
1✔
189
                        ? Double.toString(value)
1✔
190
                        : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
1✔
191
            }
192

193
            @Override
194
            public String toSourceString(String value) {
195
                return "\"" + (value.indexOf('"') == -1
1✔
196
                        ? value
197
                        : value.replace("\"", "\\\"")) + "\"";
1✔
198
            }
199

200
            @Override
201
            public String toSourceString(TypeDescription value) {
202
                return value.getActualName() + ".class";
1✔
203
            }
204
        },
205

206
        /**
207
         * A rendering dispatcher for Java 14 onward.
208
         */
209
        JAVA_14_CAPABLE_VM('{', '}', true) {
1✔
210
            @Override
211
            public String toSourceString(byte value) {
212
                return "(byte)0x" + Integer.toHexString(value & 0xFF);
1✔
213
            }
214

215
            @Override
216
            public String toSourceString(char value) {
217
                StringBuilder stringBuilder = new StringBuilder().append('\'');
1✔
218
                if (value == '\'') {
1✔
219
                    stringBuilder.append("\\'");
1✔
220
                } else {
221
                    stringBuilder.append(value);
1✔
222
                }
223
                return stringBuilder.append('\'').toString();
1✔
224
            }
225

226
            @Override
227
            public String toSourceString(long value) {
228
                return value + "L";
1✔
229
            }
230

231
            @Override
232
            public String toSourceString(float value) {
233
                return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
1✔
234
                        ? value + "f"
235
                        : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
1✔
236
            }
237

238
            @Override
239
            public String toSourceString(double value) {
240
                return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
1✔
241
                        ? Double.toString(value)
1✔
242
                        : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
1✔
243
            }
244

245
            @Override
246
            public String toSourceString(String value) {
247
                return "\"" + (value.indexOf('"') == -1
1✔
248
                        ? value
249
                        : value.replace("\"", "\\\"")) + "\"";
1✔
250
            }
251

252
            @Override
253
            public String toSourceString(TypeDescription value) {
254
                return value.getActualName() + ".class";
1✔
255
            }
256
        },
257

258
        /**
259
         * A rendering dispatcher for Java 17 onward.
260
         */
261
        JAVA_17_CAPABLE_VM('{', '}', false) {
1✔
262
            @Override
263
            public String toSourceString(byte value) {
264
                return "(byte)0x" + Integer.toHexString(value & 0xFF);
1✔
265
            }
266

267
            @Override
268
            public String toSourceString(char value) {
269
                StringBuilder stringBuilder = new StringBuilder().append('\'');
1✔
270
                if (value == '\'') {
1✔
271
                    stringBuilder.append("\\'");
1✔
272
                } else {
273
                    stringBuilder.append(value);
1✔
274
                }
275
                return stringBuilder.append('\'').toString();
1✔
276
            }
277

278
            @Override
279
            public String toSourceString(long value) {
280
                return value + "L";
1✔
281
            }
282

283
            @Override
284
            public String toSourceString(float value) {
285
                return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
1✔
286
                        ? value + "f"
287
                        : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
1✔
288
            }
289

290
            @Override
291
            public String toSourceString(double value) {
292
                return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
1✔
293
                        ? Double.toString(value)
1✔
294
                        : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
1✔
295
            }
296

297
            @Override
298
            public String toSourceString(String value) {
299
                return "\"" + (value.indexOf('"') == -1
1✔
300
                        ? value
301
                        : value.replace("\"", "\\\"")) + "\"";
1✔
302
            }
303

304
            @Override
305
            public String toSourceString(TypeDescription value) {
306
                return value.getActualName() + ".class";
1✔
307
            }
308

309
            @Override
310
            public String toTypeErrorString(Class<?> type) {
311
                return type.getName();
1✔
312
            }
313
        },
314

315
        /**
316
         * A rendering dispatcher for Java 19 onward.
317
         */
318
        JAVA_19_CAPABLE_VM('{', '}', ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5).isLessThan(ClassFileVersion.JAVA_V17)) {
1✔
319
            @Override
320
            public String toSourceString(byte value) {
321
                return "(byte)0x" + Integer.toHexString(value & 0xFF);
×
322
            }
323

324
            @Override
325
            public String toSourceString(char value) {
326
                StringBuilder stringBuilder = new StringBuilder().append('\'');
×
327
                if (value == '\'') {
×
328
                    stringBuilder.append("\\'");
×
329
                } else {
330
                    stringBuilder.append(value);
×
331
                }
332
                return stringBuilder.append('\'').toString();
×
333
            }
334

335
            @Override
336
            public String toSourceString(long value) {
337
                return value + "L";
×
338
            }
339

340
            @Override
341
            public String toSourceString(float value) {
342
                return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
×
343
                        ? value + "f"
344
                        : (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
×
345
            }
346

347
            @Override
348
            public String toSourceString(double value) {
349
                return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
×
350
                        ? Double.toString(value)
×
351
                        : (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
×
352
            }
353

354
            @Override
355
            public String toSourceString(String value) {
356
                return "\"" + (value.indexOf('"') == -1
×
357
                        ? value
358
                        : value.replace("\"", "\\\"")) + "\"";
×
359
            }
360

361
            @Override
362
            public String toSourceString(TypeDescription value) {
363
                return value.getCanonicalName() + ".class";
×
364
            }
365

366
            @Override
367
            public String toTypeErrorString(Class<?> type) {
368
                return type.getName();
×
369
            }
370
        };
371

372
        /**
373
         * The prefix text for describing a mistyped array property.
374
         */
375
        private static final String ARRAY_PREFIX = "Array with component tag: ";
376

377
        /**
378
         * The rendering dispatcher for the current VM.
379
         */
380
        public static final RenderingDispatcher CURRENT;
381

382
        /*
383
         * Resolves the rendering dispatcher to use.
384
         */
385
        static {
386
            ClassFileVersion classFileVersion = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V5);
1✔
387
            if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V19)) {
1✔
388
                CURRENT = RenderingDispatcher.JAVA_19_CAPABLE_VM;
×
389
            } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V17)) {
1✔
390
                CURRENT = RenderingDispatcher.JAVA_17_CAPABLE_VM;
×
391
            } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V14)) {
1✔
392
                CURRENT = RenderingDispatcher.JAVA_14_CAPABLE_VM;
×
393
            } else if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V9)) {
1✔
394
                CURRENT = RenderingDispatcher.JAVA_9_CAPABLE_VM;
×
395
            } else {
396
                CURRENT = RenderingDispatcher.LEGACY_VM;
1✔
397
            }
398
        }
1✔
399

400
        /**
401
         * The opening brace of an array {@link String} representation.
402
         */
403
        private final char openingBrace;
404

405
        /**
406
         * The closing brace of an array {@link String} representation.
407
         */
408
        private final char closingBrace;
409

410
        /**
411
         * If {@code true}, annotation types are represented as integer rather then character value.
412
         */
413
        private final boolean componentAsInteger;
414

415
        /**
416
         * Creates a new rendering dispatcher.
417
         *
418
         * @param openingBrace       The opening brace of an array {@link String} representation.
419
         * @param closingBrace       The closing brace of an array {@link String} representation.
420
         * @param componentAsInteger If {@code true}, annotation types are represented as characters rather then integer values.
421
         */
422
        RenderingDispatcher(char openingBrace, char closingBrace, boolean componentAsInteger) {
1✔
423
            this.openingBrace = openingBrace;
1✔
424
            this.closingBrace = closingBrace;
1✔
425
            this.componentAsInteger = componentAsInteger;
1✔
426
        }
1✔
427

428
        /**
429
         * Represents the supplied {@code boolean} value as a {@link String}.
430
         *
431
         * @param value The {@code boolean} value to render.
432
         * @return An appropriate {@link String} representation.
433
         */
434
        public String toSourceString(boolean value) {
435
            return Boolean.toString(value);
1✔
436
        }
437

438
        /**
439
         * Represents the supplied {@code boolean} value as a {@link String}.
440
         *
441
         * @param value The {@code boolean} value to render.
442
         * @return An appropriate {@link String} representation.
443
         */
444
        public String toSourceString(byte value) {
445
            return Byte.toString(value);
1✔
446
        }
447

448
        /**
449
         * Represents the supplied {@code short} value as a {@link String}.
450
         *
451
         * @param value The {@code short} value to render.
452
         * @return An appropriate {@link String} representation.
453
         */
454
        public String toSourceString(short value) {
455
            return Short.toString(value);
1✔
456
        }
457

458
        /**
459
         * Represents the supplied {@code char} value as a {@link String}.
460
         *
461
         * @param value The {@code char} value to render.
462
         * @return An appropriate {@link String} representation.
463
         */
464
        public abstract String toSourceString(char value);
465

466
        /**
467
         * Represents the supplied {@code int} value as a {@link String}.
468
         *
469
         * @param value The {@code int} value to render.
470
         * @return An appropriate {@link String} representation.
471
         */
472
        public String toSourceString(int value) {
473
            return Integer.toString(value);
1✔
474
        }
475

476
        /**
477
         * Represents the supplied {@code long} value as a {@link String}.
478
         *
479
         * @param value The {@code long} value to render.
480
         * @return An appropriate {@link String} representation.
481
         */
482
        public abstract String toSourceString(long value);
483

484
        /**
485
         * Represents the supplied {@code float} value as a {@link String}.
486
         *
487
         * @param value The {@code float} value to render.
488
         * @return An appropriate {@link String} representation.
489
         */
490
        public abstract String toSourceString(float value);
491

492
        /**
493
         * Represents the supplied {@code double} value as a {@link String}.
494
         *
495
         * @param value The {@code double} value to render.
496
         * @return An appropriate {@link String} representation.
497
         */
498
        public abstract String toSourceString(double value);
499

500
        /**
501
         * Represents the supplied {@link String} value as a {@link String}.
502
         *
503
         * @param value The {@link String} value to render.
504
         * @return An appropriate {@link String} representation.
505
         */
506
        public abstract String toSourceString(String value);
507

508
        /**
509
         * Represents the supplied {@link TypeDescription} value as a {@link String}.
510
         *
511
         * @param value The {@link TypeDescription} value to render.
512
         * @return An appropriate {@link String} representation.
513
         */
514
        public abstract String toSourceString(TypeDescription value);
515

516
        /**
517
         * Represents the supplied list elements as a {@link String}.
518
         *
519
         * @param values The elements to render where each element is represented by its {@link Object#toString()} representation.
520
         * @return An appropriate {@link String} representation.
521
         */
522
        public String toSourceString(List<?> values) {
523
            StringBuilder stringBuilder = new StringBuilder().append(openingBrace);
1✔
524
            boolean first = true;
1✔
525
            for (Object value : values) {
1✔
526
                if (first) {
1✔
527
                    first = false;
1✔
528
                } else {
529
                    stringBuilder.append(", ");
1✔
530
                }
531
                stringBuilder.append(value);
1✔
532
            }
1✔
533
            return stringBuilder.append(closingBrace).toString();
1✔
534
        }
535

536
        /**
537
         * Resolves a string for representing an inconsistently typed array of an annotation property.
538
         *
539
         * @param sort The sort of the inconsistent property.
540
         * @return A message to describe the component property.
541
         */
542
        public String toArrayErrorString(Sort sort) {
543
            return ARRAY_PREFIX + (componentAsInteger || !sort.isDefined()
1✔
544
                    ? Integer.toString(sort.getTag())
1✔
545
                    : Character.toString((char) sort.getTag()));
1✔
546
        }
547

548
        /**
549
         * Resolves a type to be represented in an error message for a mismatched type.
550
         *
551
         * @param type The represented type.
552
         * @return The name to represent.
553
         */
554
        public String toTypeErrorString(Class<?> type) {
555
            return type.toString();
1✔
556
        }
557
    }
558

559
    /**
560
     * A loaded variant of an {@link AnnotationValue}. While
561
     * implementations of this value are required to be processed successfully by a
562
     * {@link java.lang.ClassLoader} they might still be unresolved. Typical errors on loading an annotation
563
     * value are:
564
     * <ul>
565
     * <li>{@link java.lang.annotation.IncompleteAnnotationException}: An annotation does not define a value
566
     * even though no default value for a property is provided.</li>
567
     * <li>{@link java.lang.EnumConstantNotPresentException}: An annotation defines an unknown value for
568
     * a known enumeration.</li>
569
     * <li>{@link java.lang.annotation.AnnotationTypeMismatchException}: An annotation property is not
570
     * of the expected type.</li>
571
     * </ul>
572
     * Implementations of this interface must implement methods for {@link Object#hashCode()} and
573
     * {@link Object#toString()} that resemble those used for the annotation values of an actual
574
     * {@link java.lang.annotation.Annotation} implementation. Also, instances must implement
575
     * {@link java.lang.Object#equals(Object)} to return {@code true} for other instances of
576
     * this interface that represent the same annotation value.
577
     *
578
     * @param <U> The represented value's type.
579
     */
580
    interface Loaded<U> {
581

582
        /**
583
         * Returns the state of the represented loaded annotation value.
584
         *
585
         * @return The state represented by this instance.
586
         */
587
        State getState();
588

589
        /**
590
         * Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
591
         * exception if this value is either not defined or not resolved.
592
         *
593
         * @return The actual annotation value represented by this instance.
594
         */
595
        U resolve();
596

597
        /**
598
         * Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
599
         * exception if this value is either not defined or not resolved.
600
         *
601
         * @param type The value's loaded type.
602
         * @param <V>  The value's loaded type.
603
         * @return The actual annotation value represented by this instance.
604
         */
605
        <V> V resolve(Class<? extends V> type);
606

607
        /**
608
         * Verifies if this loaded value represents the supplied loaded value.
609
         *
610
         * @param value A loaded annotation value.
611
         * @return {@code true} if the supplied annotation value is represented by this annotation value.
612
         */
613
        boolean represents(Object value);
614

615
        /**
616
         * An abstract base implementation of a loaded annotation value.
617
         *
618
         * @param <W> The represented loaded type.
619
         */
620
        abstract class AbstractBase<W> implements Loaded<W> {
1✔
621

622
            /**
623
             * {@inheritDoc}
624
             */
625
            public <X> X resolve(Class<? extends X> type) {
626
                return type.cast(resolve());
1✔
627
            }
628

629
            /**
630
             * A base implementation for an unresolved property.
631
             *
632
             * @param <Z> The represented loaded type.
633
             */
634
            public abstract static class ForUnresolvedProperty<Z> extends AbstractBase<Z> {
1✔
635

636
                /**
637
                 * {@inheritDoc}
638
                 */
639
                public State getState() {
640
                    return State.UNRESOLVED;
×
641
                }
642

643
                /**
644
                 * {@inheritDoc}
645
                 */
646
                public boolean represents(Object value) {
647
                    return false;
×
648
                }
649
            }
650
        }
651
    }
652

653
    /**
654
     * Represents the state of an {@link AnnotationValue}.
655
     */
656
    enum State {
1✔
657

658
        /**
659
         * An undefined annotation value describes an annotation property which is missing such that
660
         * an {@link java.lang.annotation.IncompleteAnnotationException} would be thrown.
661
         */
662
        UNDEFINED,
1✔
663

664
        /**
665
         * An unresolved annotation value describes an annotation property which does not represent a
666
         * valid value but an exceptional state.
667
         */
668
        UNRESOLVED,
1✔
669

670
        /**
671
         * A resolved annotation value describes an annotation property with an actual value.
672
         */
673
        RESOLVED;
1✔
674

675
        /**
676
         * Returns {@code true} if the related annotation value is defined, i.e. either represents
677
         * an actual value or an exceptional state.
678
         *
679
         * @return {@code true} if the related annotation value is defined.
680
         */
681
        public boolean isDefined() {
682
            return this != UNDEFINED;
1✔
683
        }
684

685
        /**
686
         * Returns {@code true} if the related annotation value is resolved, i.e. represents an actual
687
         * value.
688
         *
689
         * @return {@code true} if the related annotation value is resolved.
690
         */
691
        public boolean isResolved() {
692
            return this == RESOLVED;
1✔
693
        }
694
    }
695

696
    /**
697
     * Represents the sort of an {@link AnnotationValue}.
698
     */
699
    enum Sort {
1✔
700

701
        /**
702
         * A {@code boolean}-typed property.
703
         */
704
        BOOLEAN('Z'),
1✔
705

706
        /**
707
         * A {@code byte}-typed property.
708
         */
709
        BYTE('B'),
1✔
710

711
        /**
712
         * A {@code short}-typed property.
713
         */
714
        SHORT('S'),
1✔
715

716
        /**
717
         * A {@code char}-typed property.
718
         */
719
        CHARACTER('C'),
1✔
720

721
        /**
722
         * An {@code int}-typed property.
723
         */
724
        INTEGER('I'),
1✔
725

726
        /**
727
         * A {@code long}-typed property.
728
         */
729
        LONG('J'),
1✔
730

731
        /**
732
         * A {@code float}-typed property.
733
         */
734
        FLOAT('F'),
1✔
735

736
        /**
737
         * A {@code double}-typed property.
738
         */
739
        DOUBLE('D'),
1✔
740

741
        /**
742
         * A {@link String}-typed property.
743
         */
744
        STRING('s'),
1✔
745

746
        /**
747
         * A {@link Class}-typed property.
748
         */
749
        TYPE('c'),
1✔
750

751
        /**
752
         * A {@link Enum}-typed property.
753
         */
754
        ENUMERATION('e'),
1✔
755

756
        /**
757
         * A {@link Annotation}-typed property.
758
         */
759
        ANNOTATION('@'),
1✔
760

761
        /**
762
         * An array-typed property.
763
         */
764
        ARRAY('['),
1✔
765

766
        /**
767
         * A property without a well-defined value.
768
         */
769
        NONE(0);
1✔
770

771
        /**
772
         * The property's tag.
773
         */
774
        private final int tag;
775

776
        /**
777
         * Creates a new sort.
778
         *
779
         * @param tag The property's tag.
780
         */
781
        Sort(int tag) {
1✔
782
            this.tag = tag;
1✔
783
        }
1✔
784

785
        /**
786
         * Resolves a sort for the provided type definition.
787
         *
788
         * @param typeDefinition The type definition to resolve.
789
         * @return The resolved sort for the provided type definition.
790
         */
791
        public static Sort of(TypeDefinition typeDefinition) {
792
            if (typeDefinition.represents(boolean.class)) {
1✔
793
                return BOOLEAN;
1✔
794
            } else if (typeDefinition.represents(byte.class)) {
1✔
795
                return BYTE;
1✔
796
            } else if (typeDefinition.represents(short.class)) {
1✔
797
                return SHORT;
1✔
798
            } else if (typeDefinition.represents(char.class)) {
1✔
799
                return CHARACTER;
1✔
800
            } else if (typeDefinition.represents(int.class)) {
1✔
801
                return INTEGER;
1✔
802
            } else if (typeDefinition.represents(long.class)) {
1✔
803
                return LONG;
1✔
804
            } else if (typeDefinition.represents(float.class)) {
1✔
805
                return FLOAT;
1✔
806
            } else if (typeDefinition.represents(double.class)) {
1✔
807
                return DOUBLE;
1✔
808
            } else if (typeDefinition.represents(String.class)) {
1✔
809
                return STRING;
1✔
810
            } else if (typeDefinition.represents(Class.class)) {
1✔
811
                return TYPE;
1✔
812
            } else if (typeDefinition.isEnum()) {
1✔
813
                return ENUMERATION;
1✔
814
            } else if (typeDefinition.isAnnotation()) {
1✔
815
                return ANNOTATION;
1✔
816
            } else if (typeDefinition.isArray()) {
1✔
817
                return ARRAY;
1✔
818
            } else {
819
                return NONE;
1✔
820
            }
821
        }
822

823
        /**
824
         * Returns the property's tag.
825
         *
826
         * @return The property's tag.
827
         */
828
        protected int getTag() {
829
            return tag;
1✔
830
        }
831

832
        /**
833
         * Returns {@code true} if the property is defined.
834
         *
835
         * @return {@code true} if the property is defined.
836
         */
837
        public boolean isDefined() {
838
            return this != NONE;
1✔
839
        }
840
    }
841

842
    /**
843
     * An abstract base implementation of an unloaded annotation value.
844
     *
845
     * @param <U> The represented unloaded type.
846
     * @param <V> The represented loaded type.
847
     */
848
    abstract class AbstractBase<U, V> implements AnnotationValue<U, V> {
1✔
849

850
        /**
851
         * {@inheritDoc}
852
         */
853
        public <W> W resolve(Class<? extends W> type) {
854
            return type.cast(resolve());
1✔
855
        }
856

857
        /**
858
         * {@inheritDoc}
859
         */
860
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property) {
861
            return filter(property, property.getReturnType());
1✔
862
        }
863
    }
864

865
    /**
866
     * Represents a primitive value, a {@link java.lang.String} or an array of the latter types.
867
     *
868
     * @param <U> The type where primitive values are represented by their boxed type.
869
     */
870
    class ForConstant<U> extends AbstractBase<U, U> {
871

872
        /**
873
         * The represented value.
874
         */
875
        private final U value;
876

877
        /**
878
         * The property delegate for the value's type.
879
         */
880
        private final PropertyDelegate propertyDelegate;
881

882
        /**
883
         * Creates a new constant annotation value.
884
         *
885
         * @param value            The represented value.
886
         * @param propertyDelegate The property delegate for the value's type.
887
         */
888
        protected ForConstant(U value, PropertyDelegate propertyDelegate) {
1✔
889
            this.value = value;
1✔
890
            this.propertyDelegate = propertyDelegate;
1✔
891
        }
1✔
892

893
        /**
894
         * Creates an annotation value for a {@code boolean} value.
895
         *
896
         * @param value The {@code boolean} value to represent.
897
         * @return An appropriate annotation value.
898
         */
899
        public static AnnotationValue<Boolean, Boolean> of(boolean value) {
900
            return new ForConstant<Boolean>(value, PropertyDelegate.ForNonArrayType.BOOLEAN);
1✔
901
        }
902

903
        /**
904
         * Creates an annotation value for a {@code byte} value.
905
         *
906
         * @param value The {@code byte} value to represent.
907
         * @return An appropriate annotation value.
908
         */
909
        public static AnnotationValue<Byte, Byte> of(byte value) {
910
            return new ForConstant<Byte>(value, PropertyDelegate.ForNonArrayType.BYTE);
1✔
911
        }
912

913
        /**
914
         * Creates an annotation value for a {@code short} value.
915
         *
916
         * @param value The {@code short} value to represent.
917
         * @return An appropriate annotation value.
918
         */
919
        public static AnnotationValue<Short, Short> of(short value) {
920
            return new ForConstant<Short>(value, PropertyDelegate.ForNonArrayType.SHORT);
1✔
921
        }
922

923
        /**
924
         * Creates an annotation value for a {@code char} value.
925
         *
926
         * @param value The {@code char} value to represent.
927
         * @return An appropriate annotation value.
928
         */
929
        public static AnnotationValue<Character, Character> of(char value) {
930
            return new ForConstant<Character>(value, PropertyDelegate.ForNonArrayType.CHARACTER);
1✔
931
        }
932

933
        /**
934
         * Creates an annotation value for a {@code int} value.
935
         *
936
         * @param value The {@code int} value to represent.
937
         * @return An appropriate annotation value.
938
         */
939
        public static AnnotationValue<Integer, Integer> of(int value) {
940
            return new ForConstant<Integer>(value, PropertyDelegate.ForNonArrayType.INTEGER);
1✔
941
        }
942

943
        /**
944
         * Creates an annotation value for a {@code long} value.
945
         *
946
         * @param value The {@code long} value to represent.
947
         * @return An appropriate annotation value.
948
         */
949
        public static AnnotationValue<Long, Long> of(long value) {
950
            return new ForConstant<Long>(value, PropertyDelegate.ForNonArrayType.LONG);
1✔
951
        }
952

953
        /**
954
         * Creates an annotation value for a {@code float} value.
955
         *
956
         * @param value The {@code float} value to represent.
957
         * @return An appropriate annotation value.
958
         */
959
        public static AnnotationValue<Float, Float> of(float value) {
960
            return new ForConstant<Float>(value, PropertyDelegate.ForNonArrayType.FLOAT);
1✔
961
        }
962

963
        /**
964
         * Creates an annotation value for a {@code double} value.
965
         *
966
         * @param value The {@code double} value to represent.
967
         * @return An appropriate annotation value.
968
         */
969
        public static AnnotationValue<Double, Double> of(double value) {
970
            return new ForConstant<Double>(value, PropertyDelegate.ForNonArrayType.DOUBLE);
1✔
971
        }
972

973
        /**
974
         * Creates an annotation value for a {@link String} value.
975
         *
976
         * @param value The {@link String} value to represent.
977
         * @return An appropriate annotation value.
978
         */
979
        public static AnnotationValue<String, String> of(String value) {
980
            return new ForConstant<String>(value, PropertyDelegate.ForNonArrayType.STRING);
1✔
981
        }
982

983
        /**
984
         * Creates an annotation value for a {@code boolean[]} value.
985
         *
986
         * @param value The {@code boolean[]} value to represent.
987
         * @return An appropriate annotation value.
988
         */
989
        public static AnnotationValue<boolean[], boolean[]> of(boolean... value) {
990
            return new ForConstant<boolean[]>(value, PropertyDelegate.ForArrayType.BOOLEAN);
1✔
991
        }
992

993
        /**
994
         * Creates an annotation value for a {@code byte[]} value.
995
         *
996
         * @param value The {@code byte[]} value to represent.
997
         * @return An appropriate annotation value.
998
         */
999
        public static AnnotationValue<byte[], byte[]> of(byte... value) {
1000
            return new ForConstant<byte[]>(value, PropertyDelegate.ForArrayType.BYTE);
1✔
1001
        }
1002

1003
        /**
1004
         * Creates an annotation value for a {@code short[]} value.
1005
         *
1006
         * @param value The {@code short[]} value to represent.
1007
         * @return An appropriate annotation value.
1008
         */
1009
        public static AnnotationValue<short[], short[]> of(short... value) {
1010
            return new ForConstant<short[]>(value, PropertyDelegate.ForArrayType.SHORT);
1✔
1011
        }
1012

1013
        /**
1014
         * Creates an annotation value for a {@code char[]} value.
1015
         *
1016
         * @param value The {@code char[]} value to represent.
1017
         * @return An appropriate annotation value.
1018
         */
1019
        public static AnnotationValue<char[], char[]> of(char... value) {
1020
            return new ForConstant<char[]>(value, PropertyDelegate.ForArrayType.CHARACTER);
1✔
1021
        }
1022

1023
        /**
1024
         * Creates an annotation value for a {@code int[]} value.
1025
         *
1026
         * @param value The {@code int[]} value to represent.
1027
         * @return An appropriate annotation value.
1028
         */
1029
        public static AnnotationValue<int[], int[]> of(int... value) {
1030
            return new ForConstant<int[]>(value, PropertyDelegate.ForArrayType.INTEGER);
1✔
1031
        }
1032

1033
        /**
1034
         * Creates an annotation value for a {@code long[]} value.
1035
         *
1036
         * @param value The {@code long[]} value to represent.
1037
         * @return An appropriate annotation value.
1038
         */
1039
        public static AnnotationValue<long[], long[]> of(long... value) {
1040
            return new ForConstant<long[]>(value, PropertyDelegate.ForArrayType.LONG);
1✔
1041
        }
1042

1043
        /**
1044
         * Creates an annotation value for a {@code float[]} value.
1045
         *
1046
         * @param value The {@code float[]} value to represent.
1047
         * @return An appropriate annotation value.
1048
         */
1049
        public static AnnotationValue<float[], float[]> of(float... value) {
1050
            return new ForConstant<float[]>(value, PropertyDelegate.ForArrayType.FLOAT);
1✔
1051
        }
1052

1053
        /**
1054
         * Creates an annotation value for a {@code double[]} value.
1055
         *
1056
         * @param value The {@code double[]} value to represent.
1057
         * @return An appropriate annotation value.
1058
         */
1059
        public static AnnotationValue<double[], double[]> of(double... value) {
1060
            return new ForConstant<double[]>(value, PropertyDelegate.ForArrayType.DOUBLE);
1✔
1061
        }
1062

1063
        /**
1064
         * Creates an annotation value for a {@code String[]} value.
1065
         *
1066
         * @param value The {@code String[]} value to represent.
1067
         * @return An appropriate annotation value.
1068
         */
1069
        public static AnnotationValue<String[], String[]> of(String... value) {
1070
            return new ForConstant<String[]>(value, PropertyDelegate.ForArrayType.STRING);
1✔
1071
        }
1072

1073
        /**
1074
         * Creates an annotation value for any constant value, i.e any primitive (wrapper) type,
1075
         * any primitive array type or any {@link String} value or array. If no constant annotation
1076
         * type is provided, a runtime exception is thrown.
1077
         *
1078
         * @param value The value to represent.
1079
         * @return An appropriate annotation value.
1080
         */
1081
        public static AnnotationValue<?, ?> of(Object value) {
1082
            if (value instanceof Boolean) {
1✔
1083
                return of(((Boolean) value).booleanValue());
1✔
1084
            } else if (value instanceof Byte) {
1✔
1085
                return of(((Byte) value).byteValue());
1✔
1086
            } else if (value instanceof Short) {
1✔
1087
                return of(((Short) value).shortValue());
1✔
1088
            } else if (value instanceof Character) {
1✔
1089
                return of(((Character) value).charValue());
1✔
1090
            } else if (value instanceof Integer) {
1✔
1091
                return of(((Integer) value).intValue());
1✔
1092
            } else if (value instanceof Long) {
1✔
1093
                return of(((Long) value).longValue());
1✔
1094
            } else if (value instanceof Float) {
1✔
1095
                return of(((Float) value).floatValue());
1✔
1096
            } else if (value instanceof Double) {
1✔
1097
                return of(((Double) value).doubleValue());
1✔
1098
            } else if (value instanceof String) {
1✔
1099
                return of((String) value);
1✔
1100
            } else if (value instanceof boolean[]) {
1✔
1101
                return of((boolean[]) value);
1✔
1102
            } else if (value instanceof byte[]) {
1✔
1103
                return of((byte[]) value);
1✔
1104
            } else if (value instanceof short[]) {
1✔
1105
                return of((short[]) value);
1✔
1106
            } else if (value instanceof char[]) {
1✔
1107
                return of((char[]) value);
1✔
1108
            } else if (value instanceof int[]) {
1✔
1109
                return of((int[]) value);
1✔
1110
            } else if (value instanceof long[]) {
1✔
1111
                return of((long[]) value);
1✔
1112
            } else if (value instanceof float[]) {
1✔
1113
                return of((float[]) value);
1✔
1114
            } else if (value instanceof double[]) {
1✔
1115
                return of((double[]) value);
1✔
1116
            } else if (value instanceof String[]) {
1✔
1117
                return of((String[]) value);
1✔
1118
            } else {
1119
                throw new IllegalArgumentException("Not a constant annotation value: " + value);
×
1120
            }
1121
        }
1122

1123
        /**
1124
         * {@inheritDoc}
1125
         */
1126
        public State getState() {
1127
            return State.RESOLVED;
1✔
1128
        }
1129

1130
        /**
1131
         * {@inheritDoc}
1132
         */
1133
        public Sort getSort() {
1134
            return Sort.of(TypeDescription.ForLoadedType.of(value.getClass()).asUnboxed());
1✔
1135
        }
1136

1137
        /**
1138
         * {@inheritDoc}
1139
         */
1140
        public AnnotationValue<U, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1141
            if (typeDefinition.asErasure().asBoxed().represents(value.getClass())) {
1✔
1142
                return this;
1✔
1143
            } else if (value.getClass().isArray()) {
1✔
1144
                return new ForMismatchedType<U, U>(property, RenderingDispatcher.CURRENT.toArrayErrorString(Sort.of(TypeDescription.ForLoadedType.of(value.getClass().getComponentType()))));
1✔
1145
            } else if (value instanceof Enum<?>) {
1✔
1146
                return new ForMismatchedType<U, U>(property, value.getClass().getName() + '.' + ((Enum<?>) value).name());
×
1147
            } else {
1148
                return new ForMismatchedType<U, U>(property, RenderingDispatcher.CURRENT.toTypeErrorString(value.getClass()) + '[' + value + ']');
1✔
1149
            }
1150
        }
1151

1152
        /**
1153
         * {@inheritDoc}
1154
         */
1155
        public U resolve() {
1156
            return value;
1✔
1157
        }
1158

1159
        /**
1160
         * {@inheritDoc}
1161
         */
1162
        public AnnotationValue.Loaded<U> load(@MaybeNull ClassLoader classLoader) {
1163
            return new Loaded<U>(value, propertyDelegate);
1✔
1164
        }
1165

1166
        @Override
1167
        @CachedReturnPlugin.Enhance("hashCode")
1168
        public int hashCode() {
1169
            return propertyDelegate.hashCode(value);
1✔
1170
        }
1171

1172
        @Override
1173
        public boolean equals(@MaybeNull Object other) {
1174
            return this == other || other instanceof AnnotationValue<?, ?> && propertyDelegate.equals(value, ((AnnotationValue<?, ?>) other).resolve());
1✔
1175
        }
1176

1177
        @Override
1178
        public String toString() {
1179
            return propertyDelegate.toString(value);
1✔
1180
        }
1181

1182
        /**
1183
         * A property delegate for a constant annotation value.
1184
         */
1185
        protected interface PropertyDelegate {
1186

1187
            /**
1188
             * Copies the provided value, if it is not immutable.
1189
             *
1190
             * @param value The value to copy.
1191
             * @param <S>   The value's type.
1192
             * @return A copy of the provided instance or the provided value, if it is immutable.
1193
             */
1194
            <S> S copy(S value);
1195

1196
            /**
1197
             * Computes the value's hash code.
1198
             *
1199
             * @param value The value for which to compute the hash code.
1200
             * @return The hash code of the provided value.
1201
             */
1202
            int hashCode(Object value);
1203

1204
            /**
1205
             * Determines if another value is equal to a constant annotation value.
1206
             *
1207
             * @param self  The value that is represented as a constant annotation value.
1208
             * @param other Any other value for which to determine equality.
1209
             * @return {@code true} if the provided value is equal to the represented value.
1210
             */
1211
            boolean equals(Object self, Object other);
1212

1213
            /**
1214
             * Renders the supplied value as a {@link String}.
1215
             *
1216
             * @param value The value to render.
1217
             * @return An appropriate {@link String} representation of the provided value.
1218
             */
1219
            String toString(Object value);
1220

1221
            /**
1222
             * A property delegate for a non-array type.
1223
             */
1224
            enum ForNonArrayType implements PropertyDelegate {
1✔
1225

1226
                /**
1227
                 * A property delegate for a {@code boolean} value.
1228
                 */
1229
                BOOLEAN {
1✔
1230
                    /** {@inheritDoc} */
1231
                    public String toString(Object value) {
1232
                        return RenderingDispatcher.CURRENT.toSourceString((Boolean) value);
1✔
1233
                    }
1234
                },
1235

1236
                /**
1237
                 * A property delegate for a {@code byte} value.
1238
                 */
1239
                BYTE {
1✔
1240
                    /** {@inheritDoc} */
1241
                    public String toString(Object value) {
1242
                        return RenderingDispatcher.CURRENT.toSourceString((Byte) value);
1✔
1243
                    }
1244
                },
1245

1246
                /**
1247
                 * A property delegate for a {@code short} value.
1248
                 */
1249
                SHORT {
1✔
1250
                    /** {@inheritDoc} */
1251
                    public String toString(Object value) {
1252
                        return RenderingDispatcher.CURRENT.toSourceString((Short) value);
1✔
1253
                    }
1254
                },
1255

1256
                /**
1257
                 * A property delegate for a {@code char} value.
1258
                 */
1259
                CHARACTER {
1✔
1260
                    /** {@inheritDoc} */
1261
                    public String toString(Object value) {
1262
                        return RenderingDispatcher.CURRENT.toSourceString((Character) value);
1✔
1263
                    }
1264
                },
1265

1266
                /**
1267
                 * A property delegate for a {@code int} value.
1268
                 */
1269
                INTEGER {
1✔
1270
                    /** {@inheritDoc} */
1271
                    public String toString(Object value) {
1272
                        return RenderingDispatcher.CURRENT.toSourceString((Integer) value);
1✔
1273
                    }
1274
                },
1275

1276
                /**
1277
                 * A property delegate for a {@code long} value.
1278
                 */
1279
                LONG {
1✔
1280
                    /** {@inheritDoc} */
1281
                    public String toString(Object value) {
1282
                        return RenderingDispatcher.CURRENT.toSourceString((Long) value);
1✔
1283
                    }
1284
                },
1285

1286
                /**
1287
                 * A property delegate for a {@code float} value.
1288
                 */
1289
                FLOAT {
1✔
1290
                    /** {@inheritDoc} */
1291
                    public String toString(Object value) {
1292
                        return RenderingDispatcher.CURRENT.toSourceString((Float) value);
1✔
1293
                    }
1294
                },
1295

1296
                /**
1297
                 * A property delegate for a {@code double} value.
1298
                 */
1299
                DOUBLE {
1✔
1300
                    /** {@inheritDoc} */
1301
                    public String toString(Object value) {
1302
                        return RenderingDispatcher.CURRENT.toSourceString((Double) value);
1✔
1303
                    }
1304
                },
1305

1306
                /**
1307
                 * A property delegate for a {@link String} value.
1308
                 */
1309
                STRING {
1✔
1310
                    /** {@inheritDoc} */
1311
                    public String toString(Object value) {
1312
                        return RenderingDispatcher.CURRENT.toSourceString((String) value);
1✔
1313
                    }
1314
                };
1315

1316
                /**
1317
                 * {@inheritDoc}
1318
                 */
1319
                public <S> S copy(S value) {
1320
                    return value;
1✔
1321
                }
1322

1323
                /**
1324
                 * {@inheritDoc}
1325
                 */
1326
                public int hashCode(Object value) {
1327
                    return value.hashCode();
1✔
1328
                }
1329

1330
                /**
1331
                 * {@inheritDoc}
1332
                 */
1333
                public boolean equals(Object self, Object other) {
1334
                    return self.equals(other);
1✔
1335
                }
1336
            }
1337

1338
            /**
1339
             * A property delegate for an array type of a constant value.
1340
             */
1341
            enum ForArrayType implements PropertyDelegate {
1✔
1342

1343
                /**
1344
                 * A property delegate for a {@code boolean[]} value.
1345
                 */
1346
                BOOLEAN {
1✔
1347
                    @Override
1348
                    protected Object doCopy(Object value) {
1349
                        return ((boolean[]) value).clone();
1✔
1350
                    }
1351

1352
                    /** {@inheritDoc} */
1353
                    public int hashCode(Object value) {
1354
                        return Arrays.hashCode((boolean[]) value);
1✔
1355
                    }
1356

1357
                    /** {@inheritDoc} */
1358
                    public boolean equals(Object self, Object other) {
1359
                        return other instanceof boolean[] && Arrays.equals((boolean[]) self, (boolean[]) other);
1✔
1360
                    }
1361

1362
                    @Override
1363
                    protected String toString(Object array, int index) {
1364
                        return ForNonArrayType.BOOLEAN.toString(Array.getBoolean(array, index));
1✔
1365
                    }
1366
                },
1367

1368
                /**
1369
                 * A property delegate for a {@code byte[]} value.
1370
                 */
1371
                BYTE {
1✔
1372
                    @Override
1373
                    protected Object doCopy(Object value) {
1374
                        return ((byte[]) value).clone();
1✔
1375
                    }
1376

1377
                    /** {@inheritDoc} */
1378
                    public int hashCode(Object value) {
1379
                        return Arrays.hashCode((byte[]) value);
1✔
1380
                    }
1381

1382
                    /** {@inheritDoc} */
1383
                    public boolean equals(Object self, Object other) {
1384
                        return other instanceof byte[] && Arrays.equals((byte[]) self, (byte[]) other);
1✔
1385
                    }
1386

1387
                    @Override
1388
                    protected String toString(Object array, int index) {
1389
                        return ForNonArrayType.BYTE.toString(Array.getByte(array, index));
1✔
1390
                    }
1391
                },
1392

1393
                /**
1394
                 * A property delegate for a {@code short[]} value.
1395
                 */
1396
                SHORT {
1✔
1397
                    @Override
1398
                    protected Object doCopy(Object value) {
1399
                        return ((short[]) value).clone();
1✔
1400
                    }
1401

1402
                    /** {@inheritDoc} */
1403
                    public int hashCode(Object value) {
1404
                        return Arrays.hashCode((short[]) value);
1✔
1405
                    }
1406

1407
                    /** {@inheritDoc} */
1408
                    public boolean equals(Object self, Object other) {
1409
                        return other instanceof short[] && Arrays.equals((short[]) self, (short[]) other);
1✔
1410
                    }
1411

1412
                    @Override
1413
                    protected String toString(Object array, int index) {
1414
                        return ForNonArrayType.SHORT.toString(Array.getShort(array, index));
1✔
1415
                    }
1416
                },
1417

1418
                /**
1419
                 * A property delegate for a {@code char[]} value.
1420
                 */
1421
                CHARACTER {
1✔
1422
                    @Override
1423
                    protected Object doCopy(Object value) {
1424
                        return ((char[]) value).clone();
1✔
1425
                    }
1426

1427
                    /** {@inheritDoc} */
1428
                    public int hashCode(Object value) {
1429
                        return Arrays.hashCode((char[]) value);
1✔
1430
                    }
1431

1432
                    /** {@inheritDoc} */
1433
                    public boolean equals(Object self, Object other) {
1434
                        return other instanceof char[] && Arrays.equals((char[]) self, (char[]) other);
1✔
1435
                    }
1436

1437
                    @Override
1438
                    protected String toString(Object array, int index) {
1439
                        return ForNonArrayType.CHARACTER.toString(Array.getChar(array, index));
1✔
1440
                    }
1441
                },
1442

1443
                /**
1444
                 * A property delegate for a {@code int[]} value.
1445
                 */
1446
                INTEGER {
1✔
1447
                    @Override
1448
                    protected Object doCopy(Object value) {
1449
                        return ((int[]) value).clone();
1✔
1450
                    }
1451

1452
                    /** {@inheritDoc} */
1453
                    public int hashCode(Object value) {
1454
                        return Arrays.hashCode((int[]) value);
1✔
1455
                    }
1456

1457
                    /** {@inheritDoc} */
1458
                    public boolean equals(Object self, Object other) {
1459
                        return other instanceof int[] && Arrays.equals((int[]) self, (int[]) other);
1✔
1460
                    }
1461

1462
                    @Override
1463
                    protected String toString(Object array, int index) {
1464
                        return ForNonArrayType.INTEGER.toString(Array.getInt(array, index));
1✔
1465
                    }
1466
                },
1467

1468
                /**
1469
                 * A property delegate for a {@code long[]} value.
1470
                 */
1471
                LONG {
1✔
1472
                    @Override
1473
                    protected Object doCopy(Object value) {
1474
                        return ((long[]) value).clone();
1✔
1475
                    }
1476

1477
                    /** {@inheritDoc} */
1478
                    public int hashCode(Object value) {
1479
                        return Arrays.hashCode((long[]) value);
1✔
1480
                    }
1481

1482
                    /** {@inheritDoc} */
1483
                    public boolean equals(Object self, Object other) {
1484
                        return other instanceof long[] && Arrays.equals((long[]) self, (long[]) other);
1✔
1485
                    }
1486

1487
                    @Override
1488
                    protected String toString(Object array, int index) {
1489
                        return ForNonArrayType.LONG.toString(Array.getLong(array, index));
1✔
1490
                    }
1491
                },
1492

1493
                /**
1494
                 * A property delegate for a {@code float[]} value.
1495
                 */
1496
                FLOAT {
1✔
1497
                    @Override
1498
                    protected Object doCopy(Object value) {
1499
                        return ((float[]) value).clone();
1✔
1500
                    }
1501

1502
                    /** {@inheritDoc} */
1503
                    public int hashCode(Object value) {
1504
                        return Arrays.hashCode((float[]) value);
1✔
1505
                    }
1506

1507
                    /** {@inheritDoc} */
1508
                    public boolean equals(Object self, Object other) {
1509
                        return other instanceof float[] && Arrays.equals((float[]) self, (float[]) other);
1✔
1510
                    }
1511

1512
                    @Override
1513
                    protected String toString(Object array, int index) {
1514
                        return ForNonArrayType.FLOAT.toString(Array.getFloat(array, index));
1✔
1515
                    }
1516
                },
1517

1518
                /**
1519
                 * A property delegate for a {@code double[]} value.
1520
                 */
1521
                DOUBLE {
1✔
1522
                    @Override
1523
                    protected Object doCopy(Object value) {
1524
                        return ((double[]) value).clone();
1✔
1525
                    }
1526

1527
                    /** {@inheritDoc} */
1528
                    public int hashCode(Object value) {
1529
                        return Arrays.hashCode((double[]) value);
1✔
1530
                    }
1531

1532
                    /** {@inheritDoc} */
1533
                    public boolean equals(Object self, Object other) {
1534
                        return other instanceof double[] && Arrays.equals((double[]) self, (double[]) other);
1✔
1535
                    }
1536

1537
                    @Override
1538
                    protected String toString(Object array, int index) {
1539
                        return ForNonArrayType.DOUBLE.toString(Array.getDouble(array, index));
1✔
1540
                    }
1541
                },
1542

1543
                /**
1544
                 * A property delegate for a {@code String[]} value.
1545
                 */
1546
                STRING {
1✔
1547
                    @Override
1548
                    protected Object doCopy(Object value) {
1549
                        return ((String[]) value).clone();
1✔
1550
                    }
1551

1552
                    /** {@inheritDoc} */
1553
                    public int hashCode(Object value) {
1554
                        return Arrays.hashCode((String[]) value);
1✔
1555
                    }
1556

1557
                    /** {@inheritDoc} */
1558
                    public boolean equals(Object self, Object other) {
1559
                        return other instanceof String[] && Arrays.equals((String[]) self, (String[]) other);
1✔
1560
                    }
1561

1562
                    @Override
1563
                    protected String toString(Object array, int index) {
1564
                        return ForNonArrayType.STRING.toString(Array.get(array, index));
1✔
1565
                    }
1566
                };
1567

1568
                /**
1569
                 * {@inheritDoc}
1570
                 */
1571
                @SuppressWarnings("unchecked")
1572
                public <S> S copy(S value) {
1573
                    return (S) doCopy(value);
1✔
1574
                }
1575

1576
                /**
1577
                 * Creates a copy of the provided array.
1578
                 *
1579
                 * @param value The array to copy.
1580
                 * @return A shallow copy of the provided array.
1581
                 */
1582
                protected abstract Object doCopy(Object value);
1583

1584
                /**
1585
                 * {@inheritDoc}
1586
                 */
1587
                public String toString(Object value) {
1588
                    List<String> elements = new ArrayList<String>(Array.getLength(value));
1✔
1589
                    for (int index = 0; index < Array.getLength(value); index++) {
1✔
1590
                        elements.add(toString(value, index));
1✔
1591
                    }
1592
                    return RenderingDispatcher.CURRENT.toSourceString(elements);
1✔
1593
                }
1594

1595
                /**
1596
                 * Renders the array element at the specified index.
1597
                 *
1598
                 * @param array The array for which an element should be rendered.
1599
                 * @param index The index of the array element to render.
1600
                 * @return A {@link String} representation of the array element at the supplied index.
1601
                 */
1602
                protected abstract String toString(Object array, int index);
1603
            }
1604
        }
1605

1606
        /**
1607
         * Represents a trivial loaded value.
1608
         *
1609
         * @param <V> The annotation properties type.
1610
         */
1611
        protected static class Loaded<V> extends AnnotationValue.Loaded.AbstractBase<V> {
1612

1613
            /**
1614
             * The represented value.
1615
             */
1616
            private final V value;
1617

1618
            /**
1619
             * The property delegate for the value's type.
1620
             */
1621
            private final PropertyDelegate propertyDelegate;
1622

1623
            /**
1624
             * Creates a new loaded representation of a constant value.
1625
             *
1626
             * @param value            The represented value.
1627
             * @param propertyDelegate The property delegate for the value's type.
1628
             */
1629
            protected Loaded(V value, PropertyDelegate propertyDelegate) {
1✔
1630
                this.value = value;
1✔
1631
                this.propertyDelegate = propertyDelegate;
1✔
1632
            }
1✔
1633

1634
            /**
1635
             * {@inheritDoc}
1636
             */
1637
            public State getState() {
1638
                return State.RESOLVED;
1✔
1639
            }
1640

1641
            /**
1642
             * {@inheritDoc}
1643
             */
1644
            public V resolve() {
1645
                return propertyDelegate.copy(value);
1✔
1646
            }
1647

1648
            /**
1649
             * {@inheritDoc}
1650
             */
1651
            public boolean represents(Object value) {
1652
                return propertyDelegate.equals(this.value, value);
1✔
1653
            }
1654

1655
            @Override
1656
            @CachedReturnPlugin.Enhance("hashCode")
1657
            public int hashCode() {
1658
                return propertyDelegate.hashCode(value);
1✔
1659
            }
1660

1661
            @Override
1662
            public boolean equals(@MaybeNull Object other) {
1663
                if (this == other) {
1✔
1664
                    return true;
×
1665
                } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1✔
1666
                    return false;
×
1667
                }
1668
                AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1✔
1669
                return annotationValue.getState().isResolved() && propertyDelegate.equals(value, annotationValue.resolve());
1✔
1670
            }
1671

1672
            @Override
1673
            public String toString() {
1674
                return propertyDelegate.toString(value);
1✔
1675
            }
1676
        }
1677
    }
1678

1679
    /**
1680
     * A description of an {@link java.lang.annotation.Annotation} as a value of another annotation.
1681
     *
1682
     * @param <U> The type of the annotation.
1683
     */
1684
    class ForAnnotationDescription<U extends Annotation> extends AbstractBase<AnnotationDescription, U> {
1685

1686
        /**
1687
         * The annotation description that this value represents.
1688
         */
1689
        private final AnnotationDescription annotationDescription;
1690

1691
        /**
1692
         * Creates a new annotation value for a given annotation description.
1693
         *
1694
         * @param annotationDescription The annotation description that this value represents.
1695
         */
1696
        public ForAnnotationDescription(AnnotationDescription annotationDescription) {
1✔
1697
            this.annotationDescription = annotationDescription;
1✔
1698
        }
1✔
1699

1700
        /**
1701
         * Creates an annotation value instance for describing the given annotation type and values.
1702
         *
1703
         * @param annotationType   The annotation type.
1704
         * @param annotationValues The values of the annotation.
1705
         * @param <V>              The type of the annotation.
1706
         * @return An annotation value representing the given annotation.
1707
         */
1708
        public static <V extends Annotation> AnnotationValue<AnnotationDescription, V> of(TypeDescription annotationType,
1709
                                                                                          Map<String, ? extends AnnotationValue<?, ?>> annotationValues) {
1710
            return new ForAnnotationDescription<V>(new AnnotationDescription.Latent(annotationType, annotationValues));
1✔
1711
        }
1712

1713
        /**
1714
         * {@inheritDoc}
1715
         */
1716
        public State getState() {
1717
            return State.RESOLVED;
1✔
1718
        }
1719

1720
        /**
1721
         * {@inheritDoc}
1722
         */
1723
        public Sort getSort() {
1724
            return Sort.ANNOTATION;
1✔
1725
        }
1726

1727
        /**
1728
         * {@inheritDoc}
1729
         */
1730
        public AnnotationValue<AnnotationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1731
            return typeDefinition.asErasure().equals(annotationDescription.getAnnotationType()) ? this : new ForMismatchedType<AnnotationDescription, U>(property, property.getReturnType().isArray()
1✔
1732
                    ? RenderingDispatcher.CURRENT.toArrayErrorString(Sort.ANNOTATION)
×
1733
                    : annotationDescription.toString());
×
1734
        }
1735

1736
        /**
1737
         * {@inheritDoc}
1738
         */
1739
        public AnnotationDescription resolve() {
1740
            return annotationDescription;
1✔
1741
        }
1742

1743
        /**
1744
         * {@inheritDoc}
1745
         */
1746
        @SuppressWarnings("unchecked")
1747
        public AnnotationValue.Loaded<U> load(@MaybeNull ClassLoader classLoader) {
1748
            try {
1749
                return new Loaded<U>(annotationDescription
1✔
1750
                        .prepare((Class<U>) Class.forName(annotationDescription.getAnnotationType().getName(), false, classLoader))
1✔
1751
                        .load());
1✔
1752
            } catch (ClassNotFoundException exception) {
×
1753
                return new ForMissingType.Loaded<U>(annotationDescription.getAnnotationType().getName(), exception);
×
1754
            }
1755
        }
1756

1757
        @Override
1758
        public int hashCode() {
1759
            return annotationDescription.hashCode();
1✔
1760
        }
1761

1762
        @Override
1763
        public boolean equals(@MaybeNull Object other) {
1764
            return this == other || other instanceof AnnotationValue<?, ?> && annotationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1✔
1765
        }
1766

1767
        @Override
1768
        public String toString() {
1769
            return annotationDescription.toString();
1✔
1770
        }
1771

1772
        /**
1773
         * A loaded version of the described annotation.
1774
         *
1775
         * @param <V> The annotation type.
1776
         */
1777
        public static class Loaded<V extends Annotation> extends AnnotationValue.Loaded.AbstractBase<V> {
1778

1779
            /**
1780
             * The loaded version of the represented annotation.
1781
             */
1782
            private final V annotation;
1783

1784
            /**
1785
             * Creates a representation of a loaded annotation.
1786
             *
1787
             * @param annotation The represented annotation.
1788
             */
1789
            public Loaded(V annotation) {
1✔
1790
                this.annotation = annotation;
1✔
1791
            }
1✔
1792

1793
            /**
1794
             * {@inheritDoc}
1795
             */
1796
            public State getState() {
1797
                return State.RESOLVED;
1✔
1798
            }
1799

1800
            /**
1801
             * {@inheritDoc}
1802
             */
1803
            public V resolve() {
1804
                return annotation;
1✔
1805
            }
1806

1807
            /**
1808
             * {@inheritDoc}
1809
             */
1810
            public boolean represents(Object value) {
1811
                return annotation.equals(value);
1✔
1812
            }
1813

1814
            @Override
1815
            public int hashCode() {
1816
                return annotation.hashCode();
1✔
1817
            }
1818

1819
            @Override
1820
            public boolean equals(@MaybeNull Object other) {
1821
                if (this == other) {
1✔
1822
                    return true;
×
1823
                } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1✔
1824
                    return false;
×
1825
                }
1826
                AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1✔
1827
                return annotationValue.getState().isResolved() && annotation.equals(annotationValue.resolve());
1✔
1828
            }
1829

1830
            @Override
1831
            public String toString() {
1832
                return annotation.toString();
1✔
1833
            }
1834
        }
1835
    }
1836

1837
    /**
1838
     * A description of an {@link java.lang.Enum} as a value of an annotation.
1839
     *
1840
     * @param <U> The type of the enumeration.
1841
     */
1842
    class ForEnumerationDescription<U extends Enum<U>> extends AbstractBase<EnumerationDescription, U> {
1843

1844
        /**
1845
         * The enumeration that is represented.
1846
         */
1847
        private final EnumerationDescription enumerationDescription;
1848

1849
        /**
1850
         * Creates a new description of an annotation value for a given enumeration.
1851
         *
1852
         * @param enumerationDescription The enumeration that is to be represented.
1853
         */
1854
        public ForEnumerationDescription(EnumerationDescription enumerationDescription) {
1✔
1855
            this.enumerationDescription = enumerationDescription;
1✔
1856
        }
1✔
1857

1858
        /**
1859
         * Creates a new annotation value for the given enumeration description.
1860
         *
1861
         * @param value The value to represent.
1862
         * @param <V>   The type of the represented enumeration.
1863
         * @return An annotation value that describes the given enumeration.
1864
         */
1865
        public static <V extends Enum<V>> AnnotationValue<EnumerationDescription, V> of(EnumerationDescription value) {
1866
            return new ForEnumerationDescription<V>(value);
1✔
1867
        }
1868

1869
        /**
1870
         * {@inheritDoc}
1871
         */
1872
        public EnumerationDescription resolve() {
1873
            return enumerationDescription;
1✔
1874
        }
1875

1876
        /**
1877
         * {@inheritDoc}
1878
         */
1879
        public State getState() {
1880
            return State.RESOLVED;
1✔
1881
        }
1882

1883
        /**
1884
         * {@inheritDoc}
1885
         */
1886
        public Sort getSort() {
1887
            return Sort.ENUMERATION;
1✔
1888
        }
1889

1890
        /**
1891
         * {@inheritDoc}
1892
         */
1893
        public AnnotationValue<EnumerationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
1894
            return typeDefinition.asErasure().equals(enumerationDescription.getEnumerationType()) ? this : new ForMismatchedType<EnumerationDescription, U>(property, property.getReturnType().isArray()
1✔
1895
                    ? RenderingDispatcher.CURRENT.toArrayErrorString(Sort.ENUMERATION)
×
1896
                    : enumerationDescription.getEnumerationType().getName() + '.' + enumerationDescription.getValue());
×
1897
        }
1898

1899
        /**
1900
         * {@inheritDoc}
1901
         */
1902
        @SuppressWarnings("unchecked")
1903
        public AnnotationValue.Loaded<U> load(@MaybeNull ClassLoader classLoader) {
1904
            try {
1905
                return new Loaded<U>(enumerationDescription.load((Class<U>) Class.forName(enumerationDescription.getEnumerationType().getName(), false, classLoader)));
1✔
1906
            } catch (ClassNotFoundException exception) {
×
1907
                return new ForMissingType.Loaded<U>(enumerationDescription.getEnumerationType().getName(), exception);
×
1908
            }
1909
        }
1910

1911
        @Override
1912
        public int hashCode() {
1913
            return enumerationDescription.hashCode();
1✔
1914
        }
1915

1916
        @Override
1917
        public boolean equals(@MaybeNull Object other) {
1918
            return this == other || other instanceof AnnotationValue<?, ?> && enumerationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1✔
1919
        }
1920

1921
        @Override
1922
        public String toString() {
1923
            return enumerationDescription.toString();
1✔
1924
        }
1925

1926
        /**
1927
         * A loaded representation of an enumeration value.
1928
         *
1929
         * @param <V> The type of the represented enumeration.
1930
         */
1931
        public static class Loaded<V extends Enum<V>> extends AnnotationValue.Loaded.AbstractBase<V> {
1932

1933
            /**
1934
             * The represented enumeration.
1935
             */
1936
            private final V enumeration;
1937

1938
            /**
1939
             * Creates a loaded version of an enumeration description.
1940
             *
1941
             * @param enumeration The represented enumeration.
1942
             */
1943
            public Loaded(V enumeration) {
1✔
1944
                this.enumeration = enumeration;
1✔
1945
            }
1✔
1946

1947
            /**
1948
             * {@inheritDoc}
1949
             */
1950
            public State getState() {
1951
                return State.RESOLVED;
1✔
1952
            }
1953

1954
            /**
1955
             * {@inheritDoc}
1956
             */
1957
            public V resolve() {
1958
                return enumeration;
1✔
1959
            }
1960

1961
            /**
1962
             * {@inheritDoc}
1963
             */
1964
            public boolean represents(Object value) {
1965
                return enumeration.equals(value);
1✔
1966
            }
1967

1968
            @Override
1969
            public int hashCode() {
1970
                return enumeration.hashCode();
1✔
1971
            }
1972

1973
            @Override
1974
            public boolean equals(@MaybeNull Object other) {
1975
                if (this == other) {
1✔
1976
                    return true;
×
1977
                } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1✔
1978
                    return false;
×
1979
                }
1980
                AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1✔
1981
                return annotationValue.getState().isResolved() && enumeration.equals(annotationValue.resolve());
1✔
1982
            }
1983

1984
            @Override
1985
            public String toString() {
1986
                return enumeration.toString();
1✔
1987
            }
1988

1989
            /**
1990
             * <p>
1991
             * Represents an annotation's enumeration value for a runtime type that is not an enumeration type.
1992
             * </p>
1993
             * <p>
1994
             * <b>Note</b>: Neither of {@link Object#hashCode()}, {@link Object#toString()} and
1995
             * {@link java.lang.Object#equals(Object)} are implemented specifically what resembles the way
1996
             * such exceptional states are represented in the Open JDK's annotation implementations.
1997
             * </p>
1998
             */
1999
            public static class WithIncompatibleRuntimeType extends AnnotationValue.Loaded.AbstractBase<Enum<?>> {
2000

2001
                /**
2002
                 * The runtime type which is not an enumeration type.
2003
                 */
2004
                private final Class<?> type;
2005

2006
                /**
2007
                 * Creates a new representation for an incompatible runtime type.
2008
                 *
2009
                 * @param type The runtime type which is not an enumeration type.
2010
                 */
2011
                public WithIncompatibleRuntimeType(Class<?> type) {
1✔
2012
                    this.type = type;
1✔
2013
                }
1✔
2014

2015
                /**
2016
                 * {@inheritDoc}
2017
                 */
2018
                public State getState() {
2019
                    return State.UNRESOLVED;
×
2020
                }
2021

2022
                /**
2023
                 * {@inheritDoc}
2024
                 */
2025
                public Enum<?> resolve() {
2026
                    throw new IncompatibleClassChangeError("Not an enumeration type: " + type.getName());
1✔
2027
                }
2028

2029
                /**
2030
                 * {@inheritDoc}
2031
                 */
2032
                public boolean represents(Object value) {
2033
                    return false;
×
2034
                }
2035

2036
                /* hashCode, equals and toString are intentionally not implemented */
2037
            }
2038
        }
2039

2040
        /**
2041
         * Represents a property with an enumeration constant that is not defined by an enumeration type.
2042
         *
2043
         * @param <U> The enumerationl type.
2044
         */
2045
        public static class WithUnknownConstant<U extends Enum<U>> extends AbstractBase<EnumerationDescription, U> {
2046

2047
            /**
2048
             * A description of the enumeration type.
2049
             */
2050
            private final TypeDescription typeDescription;
2051

2052
            /**
2053
             * The enumeration constant value.
2054
             */
2055
            private final String value;
2056

2057
            /**
2058
             * Creates a property description for an enumeration value that does not exist for the enumeration type.
2059
             *
2060
             * @param typeDescription A description of the enumeration type.
2061
             * @param value           The enumeration constant value.
2062
             */
2063
            public WithUnknownConstant(TypeDescription typeDescription, String value) {
×
2064
                this.typeDescription = typeDescription;
×
2065
                this.value = value;
×
2066
            }
×
2067

2068
            /**
2069
             * {@inheritDoc}
2070
             */
2071
            public State getState() {
2072
                return State.UNRESOLVED;
×
2073
            }
2074

2075
            /**
2076
             * {@inheritDoc}
2077
             */
2078
            public Sort getSort() {
2079
                return Sort.NONE;
×
2080
            }
2081

2082
            /**
2083
             * {@inheritDoc}
2084
             */
2085
            public AnnotationValue<EnumerationDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2086
                return this;
×
2087
            }
2088

2089
            /**
2090
             * {@inheritDoc}
2091
             */
2092
            public EnumerationDescription resolve() {
2093
                throw new IllegalStateException(typeDescription + " does not declare enumeration constant " + value);
×
2094
            }
2095

2096
            /**
2097
             * {@inheritDoc}
2098
             */
2099
            @SuppressWarnings("unchecked")
2100
            public AnnotationValue.Loaded<U> load(@MaybeNull ClassLoader classLoader) {
2101
                try {
2102
                    // Type casting to Object is required for Java 6 compilability.
2103
                    return (AnnotationValue.Loaded<U>) (Object) new Loaded((Class<Enum<?>>) Class.forName(typeDescription.getName(), false, classLoader), value);
×
2104
                } catch (ClassNotFoundException exception) {
×
2105
                    return new ForMissingType.Loaded<U>(typeDescription.getName(), exception);
×
2106
                }
2107
            }
2108

2109
            /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2110

2111
            @Override
2112
            public String toString() {
2113
                return value + " /* Warning: constant not present! */";
×
2114
            }
2115

2116
            /**
2117
             * Represents a property with an enumeration constant that is not defined by an enumeration type.
2118
             */
2119
            public static class Loaded extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<Enum<?>> {
2120

2121
                /**
2122
                 * The loaded enumeration type.
2123
                 */
2124
                private final Class<? extends Enum<?>> enumType;
2125

2126
                /**
2127
                 * The value for which no enumeration constant exists at runtime.
2128
                 */
2129
                private final String value;
2130

2131
                /**
2132
                 * Creates a new representation for an unknown enumeration constant of an annotation.
2133
                 *
2134
                 * @param enumType The loaded enumeration type.
2135
                 * @param value    The value for which no enumeration constant exists at runtime.
2136
                 */
2137
                public Loaded(Class<? extends Enum<?>> enumType, String value) {
1✔
2138
                    this.enumType = enumType;
1✔
2139
                    this.value = value;
1✔
2140
                }
1✔
2141

2142
                /**
2143
                 * {@inheritDoc}
2144
                 */
2145
                public Enum<?> resolve() {
2146
                    throw new EnumConstantNotPresentException(enumType, value);
1✔
2147
                }
2148

2149
                /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2150

2151
                @Override
2152
                public String toString() {
2153
                    return value + " /* Warning: constant not present! */";
×
2154
                }
2155
            }
2156
        }
2157
    }
2158

2159
    /**
2160
     * A description of a {@link java.lang.Class} as a value of an annotation.
2161
     *
2162
     * @param <U> The type of the {@link java.lang.Class} that is described.
2163
     */
2164
    class ForTypeDescription<U extends Class<U>> extends AbstractBase<TypeDescription, U> {
2165

2166
        /**
2167
         * Indicates to a class loading process that class initializers are not required to be executed when loading a type.
2168
         */
2169
        private static final boolean NO_INITIALIZATION = false;
2170

2171
        /**
2172
         * A map of primitive types to their loaded representation.
2173
         */
2174
        private static final Map<TypeDescription, Class<?>> PRIMITIVE_TYPES;
2175

2176
        /*
2177
         * Initializes the maps of primitive types by their description.
2178
         */
2179
        static {
2180
            PRIMITIVE_TYPES = new HashMap<TypeDescription, Class<?>>();
1✔
2181
            for (Class<?> type : new Class<?>[]{boolean.class,
1✔
2182
                    byte.class,
2183
                    short.class,
2184
                    char.class,
2185
                    int.class,
2186
                    long.class,
2187
                    float.class,
2188
                    double.class,
2189
                    void.class}) {
2190
                PRIMITIVE_TYPES.put(TypeDescription.ForLoadedType.of(type), type);
1✔
2191
            }
2192
        }
1✔
2193

2194
        /**
2195
         * A description of the represented type.
2196
         */
2197
        private final TypeDescription typeDescription;
2198

2199
        /**
2200
         * Creates a new annotation value that represents a type.
2201
         *
2202
         * @param typeDescription The represented type.
2203
         */
2204
        public ForTypeDescription(TypeDescription typeDescription) {
1✔
2205
            this.typeDescription = typeDescription;
1✔
2206
        }
1✔
2207

2208
        /**
2209
         * Creates an annotation value for representing the given type.
2210
         *
2211
         * @param typeDescription The type to represent.
2212
         * @param <V>             The represented type.
2213
         * @return An annotation value that represents the given type.
2214
         */
2215
        public static <V extends Class<V>> AnnotationValue<TypeDescription, V> of(TypeDescription typeDescription) {
2216
            return new ForTypeDescription<V>(typeDescription);
1✔
2217
        }
2218

2219
        /**
2220
         * {@inheritDoc}
2221
         */
2222
        public State getState() {
2223
            return State.RESOLVED;
1✔
2224
        }
2225

2226
        /**
2227
         * {@inheritDoc}
2228
         */
2229
        public Sort getSort() {
2230
            return Sort.TYPE;
1✔
2231
        }
2232

2233
        /**
2234
         * {@inheritDoc}
2235
         */
2236
        public AnnotationValue<TypeDescription, U> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2237
            return typeDefinition.asErasure().represents(Class.class) ? this : new ForMismatchedType<TypeDescription, U>(property, property.getReturnType().isArray()
1✔
2238
                    ? RenderingDispatcher.CURRENT.toArrayErrorString(Sort.TYPE)
×
2239
                    : Class.class.getName() + '[' + typeDescription.getName() + ']');
×
2240
        }
2241

2242
        /**
2243
         * {@inheritDoc}
2244
         */
2245
        public TypeDescription resolve() {
2246
            return typeDescription;
1✔
2247
        }
2248

2249
        /**
2250
         * {@inheritDoc}
2251
         */
2252
        @SuppressWarnings("unchecked")
2253
        public AnnotationValue.Loaded<U> load(@MaybeNull ClassLoader classLoader) {
2254
            try {
2255
                return new Loaded<U>((U) (typeDescription.isPrimitive()
1✔
2256
                        ? PRIMITIVE_TYPES.get(typeDescription)
1✔
2257
                        : Class.forName(typeDescription.getName(), NO_INITIALIZATION, classLoader)));
1✔
2258
            } catch (ClassNotFoundException exception) {
×
2259
                return new ForMissingType.Loaded<U>(typeDescription.getName(), exception);
×
2260
            }
2261
        }
2262

2263
        @Override
2264
        public int hashCode() {
2265
            return typeDescription.hashCode();
1✔
2266
        }
2267

2268
        @Override
2269
        public boolean equals(@MaybeNull Object other) {
2270
            return this == other || other instanceof AnnotationValue<?, ?> && typeDescription.equals(((AnnotationValue<?, ?>) other).resolve());
1✔
2271
        }
2272

2273
        @Override
2274
        public String toString() {
2275
            return RenderingDispatcher.CURRENT.toSourceString(typeDescription);
1✔
2276
        }
2277

2278
        /**
2279
         * A loaded annotation value for a given type.
2280
         *
2281
         * @param <U> The represented type.
2282
         */
2283
        protected static class Loaded<U extends Class<U>> extends AnnotationValue.Loaded.AbstractBase<U> {
2284

2285
            /**
2286
             * The represented type.
2287
             */
2288
            private final U type;
2289

2290
            /**
2291
             * Creates a new loaded annotation value for a given type.
2292
             *
2293
             * @param type The represented type.
2294
             */
2295
            public Loaded(U type) {
1✔
2296
                this.type = type;
1✔
2297
            }
1✔
2298

2299
            /**
2300
             * {@inheritDoc}
2301
             */
2302
            public State getState() {
2303
                return State.RESOLVED;
1✔
2304
            }
2305

2306
            /**
2307
             * {@inheritDoc}
2308
             */
2309
            public U resolve() {
2310
                return type;
1✔
2311
            }
2312

2313
            /**
2314
             * {@inheritDoc}
2315
             */
2316
            public boolean represents(Object value) {
2317
                return type.equals(value);
1✔
2318
            }
2319

2320
            @Override
2321
            public int hashCode() {
2322
                return type.hashCode();
1✔
2323
            }
2324

2325
            @Override
2326
            public boolean equals(@MaybeNull Object other) {
2327
                if (this == other) {
1✔
2328
                    return true;
×
2329
                } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1✔
2330
                    return false;
×
2331
                }
2332
                AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1✔
2333
                return annotationValue.getState().isResolved() && type.equals(annotationValue.resolve());
1✔
2334
            }
2335

2336
            @Override
2337
            public String toString() {
2338
                return RenderingDispatcher.CURRENT.toSourceString(TypeDescription.ForLoadedType.of(type));
1✔
2339
            }
2340
        }
2341
    }
2342

2343
    /**
2344
     * Describes a complex array that is the value of an annotation. Complex arrays are arrays that might trigger the loading
2345
     * of user-defined types, i.e. {@link java.lang.Class}, {@link java.lang.annotation.Annotation} and {@link java.lang.Enum}
2346
     * instances.
2347
     *
2348
     * @param <U> The array type of the annotation's value when it is not loaded.
2349
     * @param <V> The array type of the annotation's value when it is loaded.
2350
     */
2351
    class ForDescriptionArray<U, V> extends AbstractBase<U, V> {
2352

2353
        /**
2354
         * The component type for arrays containing unloaded versions of the annotation array's values.
2355
         */
2356
        private final Class<?> unloadedComponentType;
2357

2358
        /**
2359
         * A description of the component type when it is loaded.
2360
         */
2361
        private final TypeDescription componentType;
2362

2363
        /**
2364
         * A list of values of the array elements.
2365
         */
2366
        private final List<? extends AnnotationValue<?, ?>> values;
2367

2368
        /**
2369
         * Creates a new complex array.
2370
         *
2371
         * @param unloadedComponentType The component type for arrays containing unloaded versions of the annotation array's values.
2372
         * @param componentType         A description of the component type when it is loaded.
2373
         * @param values                A list of values of the array elements.
2374
         */
2375
        public ForDescriptionArray(Class<?> unloadedComponentType,
2376
                                   TypeDescription componentType,
2377
                                   List<? extends AnnotationValue<?, ?>> values) {
1✔
2378
            this.unloadedComponentType = unloadedComponentType;
1✔
2379
            this.componentType = componentType;
1✔
2380
            this.values = values;
1✔
2381
        }
1✔
2382

2383
        /**
2384
         * Creates a new complex array of enumeration descriptions.
2385
         *
2386
         * @param enumerationType        A description of the type of the enumeration.
2387
         * @param enumerationDescription An array of enumeration descriptions.
2388
         * @param <W>                    The type of the enumeration.
2389
         * @return A description of the array of enumeration values.
2390
         */
2391
        public static <W extends Enum<W>> AnnotationValue<EnumerationDescription[], W[]> of(TypeDescription enumerationType,
2392
                                                                                            EnumerationDescription[] enumerationDescription) {
2393
            List<AnnotationValue<EnumerationDescription, W>> values = new ArrayList<AnnotationValue<EnumerationDescription, W>>(enumerationDescription.length);
1✔
2394
            for (EnumerationDescription value : enumerationDescription) {
1✔
2395
                if (!value.getEnumerationType().equals(enumerationType)) {
1✔
2396
                    throw new IllegalArgumentException(value + " is not of " + enumerationType);
1✔
2397
                }
2398
                values.add(ForEnumerationDescription.<W>of(value));
1✔
2399
            }
2400
            return new ForDescriptionArray<EnumerationDescription[], W[]>(EnumerationDescription.class, enumerationType, values);
1✔
2401
        }
2402

2403
        /**
2404
         * Creates a new complex array of annotation descriptions.
2405
         *
2406
         * @param annotationType        A description of the type of the annotation.
2407
         * @param annotationDescription An array of annotation descriptions.
2408
         * @param <W>                   The type of the annotation.
2409
         * @return A description of the array of enumeration values.
2410
         */
2411
        public static <W extends Annotation> AnnotationValue<AnnotationDescription[], W[]> of(TypeDescription annotationType,
2412
                                                                                              AnnotationDescription[] annotationDescription) {
2413
            List<AnnotationValue<AnnotationDescription, W>> values = new ArrayList<AnnotationValue<AnnotationDescription, W>>(annotationDescription.length);
1✔
2414
            for (AnnotationDescription value : annotationDescription) {
1✔
2415
                if (!value.getAnnotationType().equals(annotationType)) {
1✔
2416
                    throw new IllegalArgumentException(value + " is not of " + annotationType);
1✔
2417
                }
2418
                values.add(new ForAnnotationDescription<W>(value));
1✔
2419
            }
2420
            return new ForDescriptionArray<AnnotationDescription[], W[]>(AnnotationDescription.class, annotationType, values);
1✔
2421
        }
2422

2423
        /**
2424
         * Creates a new complex array of annotation descriptions.
2425
         *
2426
         * @param typeDescription A description of the types contained in the array.
2427
         * @return A description of the array of enumeration values.
2428
         */
2429
        @SuppressWarnings({"unchecked", "rawtypes", "cast"})
2430
        public static AnnotationValue<TypeDescription[], Class<?>[]> of(TypeDescription[] typeDescription) {
2431
            List<AnnotationValue<TypeDescription, Class<?>>> values = new ArrayList<AnnotationValue<TypeDescription, Class<?>>>(typeDescription.length);
1✔
2432
            for (TypeDescription value : typeDescription) {
1✔
2433
                values.add((AnnotationValue) ForTypeDescription.<Class>of(value));
1✔
2434
            }
2435
            return new ForDescriptionArray<TypeDescription[], Class<?>[]>(TypeDescription.class, TypeDescription.ForLoadedType.of(Class.class), values);
1✔
2436
        }
2437

2438
        /**
2439
         * {@inheritDoc}
2440
         */
2441
        public State getState() {
2442
            return State.RESOLVED;
1✔
2443
        }
2444

2445
        /**
2446
         * {@inheritDoc}
2447
         */
2448
        public Sort getSort() {
2449
            return Sort.ARRAY;
×
2450
        }
2451

2452
        /**
2453
         * {@inheritDoc}
2454
         */
2455
        @SuppressWarnings("unchecked")
2456
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
2457
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2458
            if (typeDefinition.isArray() && typeDefinition.getComponentType().asErasure().equals(componentType)) {
1✔
2459
                for (AnnotationValue<?, ?> value : values) {
1✔
2460
                    if (value.getSort() != Sort.of(componentType)) {
1✔
2461
                        return new ForMismatchedType<U, V>(property, RenderingDispatcher.CURRENT.toArrayErrorString(value.getSort()));
×
2462
                    }
2463
                    value = value.filter(property, typeDefinition.getComponentType());
1✔
2464
                    if (value.getState() != State.RESOLVED) {
1✔
2465
                        return (AnnotationValue<U, V>) value;
×
2466
                    }
2467
                }
1✔
2468
                return this;
1✔
2469
            } else {
2470
                return new ForMismatchedType<U, V>(property, RenderingDispatcher.CURRENT.toArrayErrorString(Sort.of(componentType)));
×
2471
            }
2472
        }
2473

2474
        /**
2475
         * {@inheritDoc}
2476
         */
2477
        public U resolve() {
2478
            @SuppressWarnings("unchecked")
2479
            U resolved = (U) Array.newInstance(unloadedComponentType, values.size());
1✔
2480
            int index = 0;
1✔
2481
            for (AnnotationValue<?, ?> value : values) {
1✔
2482
                Array.set(resolved, index++, value.resolve());
1✔
2483
            }
1✔
2484
            return resolved;
1✔
2485
        }
2486

2487
        /**
2488
         * {@inheritDoc}
2489
         */
2490
        @SuppressWarnings("unchecked")
2491
        public AnnotationValue.Loaded<V> load(@MaybeNull ClassLoader classLoader) {
2492
            List<AnnotationValue.Loaded<?>> values = new ArrayList<AnnotationValue.Loaded<?>>(this.values.size());
1✔
2493
            for (AnnotationValue<?, ?> value : this.values) {
1✔
2494
                values.add(value.load(classLoader));
1✔
2495
            }
1✔
2496
            try {
2497
                return new Loaded<V>((Class<V>) (componentType.isPrimitive()
1✔
2498
                        ? unloadedComponentType
2499
                        : Class.forName(componentType.getName(), false, classLoader)), values);
1✔
2500
            } catch (ClassNotFoundException exception) {
×
2501
                return new ForMissingType.Loaded<V>(componentType.getName(), exception);
×
2502
            }
2503
        }
2504

2505
        @Override
2506
        @CachedReturnPlugin.Enhance("hashCode")
2507
        public int hashCode() {
2508
            int result = 1;
1✔
2509
            for (AnnotationValue<?, ?> value : values) {
1✔
2510
                result = 31 * result + value.hashCode();
1✔
2511
            }
1✔
2512
            return result;
1✔
2513
        }
2514

2515
        @Override
2516
        public boolean equals(@MaybeNull Object other) {
2517
            if (this == other) {
1✔
2518
                return true;
×
2519
            } else if (!(other instanceof AnnotationValue<?, ?>)) {
1✔
2520
                return false;
×
2521
            }
2522
            AnnotationValue<?, ?> annotationValue = (AnnotationValue<?, ?>) other;
1✔
2523
            Object value = annotationValue.resolve();
1✔
2524
            if (!value.getClass().isArray()) {
1✔
2525
                return false;
×
2526
            }
2527
            if (values.size() != Array.getLength(value)) {
1✔
2528
                return false;
×
2529
            }
2530
            Iterator<? extends AnnotationValue<?, ?>> iterator = values.iterator();
1✔
2531
            for (int index = 0; index < values.size(); index++) {
1✔
2532
                AnnotationValue<?, ?> self = iterator.next();
1✔
2533
                if (!self.resolve().equals(Array.get(value, index))) {
1✔
2534
                    return false;
×
2535
                }
2536
            }
2537
            return true;
1✔
2538
        }
2539

2540
        @Override
2541
        public String toString() {
2542
            return RenderingDispatcher.CURRENT.toSourceString(values);
1✔
2543
        }
2544

2545
        /**
2546
         * Represents a loaded complex array.
2547
         *
2548
         * @param <W> The type of the loaded array.
2549
         */
2550
        protected static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase<W> {
2551

2552
            /**
2553
             * The loaded component type of the array.
2554
             */
2555
            private final Class<W> componentType;
2556

2557
            /**
2558
             * A list of loaded values that the represented array contains.
2559
             */
2560
            private final List<AnnotationValue.Loaded<?>> values;
2561

2562
            /**
2563
             * Creates a new loaded value representing a complex array.
2564
             *
2565
             * @param componentType The loaded component type of the array.
2566
             * @param values        A list of loaded values that the represented array contains.
2567
             */
2568
            protected Loaded(Class<W> componentType, List<AnnotationValue.Loaded<?>> values) {
1✔
2569
                this.componentType = componentType;
1✔
2570
                this.values = values;
1✔
2571
            }
1✔
2572

2573
            /**
2574
             * {@inheritDoc}
2575
             */
2576
            public State getState() {
2577
                for (AnnotationValue.Loaded<?> value : values) {
1✔
2578
                    if (!value.getState().isResolved()) {
1✔
2579
                        return State.UNRESOLVED;
×
2580
                    }
2581
                }
1✔
2582
                return State.RESOLVED;
1✔
2583
            }
2584

2585
            /**
2586
             * {@inheritDoc}
2587
             */
2588
            public W resolve() {
2589
                @SuppressWarnings("unchecked")
2590
                W array = (W) Array.newInstance(componentType, values.size());
1✔
2591
                int index = 0;
1✔
2592
                for (AnnotationValue.Loaded<?> annotationValue : values) {
1✔
2593
                    Array.set(array, index++, annotationValue.resolve());
1✔
2594
                }
1✔
2595
                return array;
1✔
2596
            }
2597

2598
            /**
2599
             * {@inheritDoc}
2600
             */
2601
            public boolean represents(Object value) {
2602
                if (!value.getClass().isArray()) return false;
1✔
2603
                if (value.getClass().getComponentType() != componentType) return false;
1✔
2604
                if (values.size() != Array.getLength(value)) return false;
1✔
2605
                Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
1✔
2606
                for (int index = 0; index < Array.getLength(value); index++) {
1✔
2607
                    AnnotationValue.Loaded<?> self = iterator.next();
1✔
2608
                    if (!self.represents(Array.get(value, index))) {
1✔
2609
                        return false;
×
2610
                    }
2611
                }
2612
                return true;
1✔
2613
            }
2614

2615
            @Override
2616
            @CachedReturnPlugin.Enhance("hashCode")
2617
            public int hashCode() {
2618
                int result = 1;
1✔
2619
                for (AnnotationValue.Loaded<?> value : values) {
1✔
2620
                    result = 31 * result + value.hashCode();
1✔
2621
                }
1✔
2622
                return result;
1✔
2623
            }
2624

2625
            @Override
2626
            public boolean equals(@MaybeNull Object other) {
2627
                if (this == other) {
1✔
2628
                    return true;
×
2629
                } else if (!(other instanceof AnnotationValue.Loaded<?>)) {
1✔
2630
                    return false;
×
2631
                }
2632
                AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
1✔
2633
                if (!annotationValue.getState().isResolved()) {
1✔
2634
                    return false;
×
2635
                }
2636
                Object value = annotationValue.resolve();
1✔
2637
                if (!value.getClass().isArray()) {
1✔
2638
                    return false;
×
2639
                }
2640
                if (values.size() != Array.getLength(value)) {
1✔
2641
                    return false;
×
2642
                }
2643
                Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
1✔
2644
                for (int index = 0; index < Array.getLength(value); index++) {
1✔
2645
                    AnnotationValue.Loaded<?> self = iterator.next();
1✔
2646
                    if (!self.getState().isResolved() || !self.resolve().equals(Array.get(value, index))) {
1✔
2647
                        return false;
×
2648
                    }
2649
                }
2650
                return true;
1✔
2651
            }
2652

2653
            @Override
2654
            public String toString() {
2655
                return RenderingDispatcher.CURRENT.toSourceString(values);
1✔
2656
            }
2657
        }
2658
    }
2659

2660
    /**
2661
     * An annotation value for a type that could not be loaded.
2662
     *
2663
     * @param <U> The type of the annotation's value when it is not loaded.
2664
     * @param <V> The type of the annotation's value when it is loaded.
2665
     */
2666
    class ForMissingType<U, V> extends AbstractBase<U, V> {
2667

2668
        /**
2669
         * The type's binary name.
2670
         */
2671
        private final String typeName;
2672

2673
        /**
2674
         * Creates a new annotation value for a type that cannot be loaded.
2675
         *
2676
         * @param typeName The type's binary name.
2677
         */
2678
        public ForMissingType(String typeName) {
×
2679
            this.typeName = typeName;
×
2680
        }
×
2681

2682
        /**
2683
         * {@inheritDoc}
2684
         */
2685
        public State getState() {
2686
            return State.UNRESOLVED;
×
2687
        }
2688

2689
        /**
2690
         * {@inheritDoc}
2691
         */
2692
        public Sort getSort() {
2693
            return Sort.NONE;
×
2694
        }
2695

2696
        /**
2697
         * {@inheritDoc}
2698
         */
2699
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2700
            return this;
×
2701
        }
2702

2703
        /**
2704
         * {@inheritDoc}
2705
         */
2706
        public U resolve() {
2707
            throw new IllegalStateException("Type not found: " + typeName);
×
2708
        }
2709

2710
        /**
2711
         * {@inheritDoc}
2712
         */
2713
        public AnnotationValue.Loaded<V> load(@MaybeNull ClassLoader classLoader) {
2714
            return new Loaded<V>(typeName, new ClassNotFoundException(typeName));
×
2715
        }
2716

2717
        /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2718

2719
        @Override
2720
        public String toString() {
2721
            return typeName + ".class /* Warning: type not present! */";
×
2722
        }
2723

2724
        /**
2725
         * Represents a missing type during an annotation's resolution.
2726
         *
2727
         * @param <U> The represented type.
2728
         */
2729
        public static class Loaded<U> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<U> {
2730

2731
            /**
2732
             * The type's binary name.
2733
             */
2734
            private final String typeName;
2735

2736
            /**
2737
             * The exception describing the missing type.
2738
             */
2739
            private final ClassNotFoundException exception;
2740

2741
            /**
2742
             * The type's binary name.
2743
             *
2744
             * @param typeName  The type's binary name.
2745
             * @param exception The exception describing the missing type.
2746
             */
2747
            public Loaded(String typeName, ClassNotFoundException exception) {
×
2748
                this.typeName = typeName;
×
2749
                this.exception = exception;
×
2750
            }
×
2751

2752
            /**
2753
             * {@inheritDoc}
2754
             */
2755
            public U resolve() {
2756
                throw new TypeNotPresentException(typeName, exception);
×
2757
            }
2758

2759
            @Override
2760
            public String toString() {
2761
                return typeName + ".class /* Warning: type not present! */";
×
2762
            }
2763
        }
2764
    }
2765

2766
    /**
2767
     * Describes an annotation value that does not match the annotation' type for a property.
2768
     *
2769
     * @param <U> The type of the annotation's value when it is not loaded.
2770
     * @param <V> The type of the annotation's value when it is loaded.
2771
     */
2772
    class ForMismatchedType<U, V> extends AbstractBase<U, V> {
2773

2774
        /**
2775
         * The property that does not defines a non-matching value.
2776
         */
2777
        private final MethodDescription.InDefinedShape property;
2778

2779
        /**
2780
         * A value description of the property.
2781
         */
2782
        private final String value;
2783

2784
        /**
2785
         * Creates an annotation description for a mismatched type.
2786
         *
2787
         * @param property The property that does not defines a non-matching value.
2788
         * @param value    A value description of the property.
2789
         */
2790
        public ForMismatchedType(MethodDescription.InDefinedShape property, String value) {
1✔
2791
            this.property = property;
1✔
2792
            this.value = value;
1✔
2793
        }
1✔
2794

2795
        /**
2796
         * {@inheritDoc}
2797
         */
2798
        public State getState() {
2799
            return State.UNRESOLVED;
1✔
2800
        }
2801

2802
        /**
2803
         * {@inheritDoc}
2804
         */
2805
        public Sort getSort() {
2806
            return Sort.NONE;
×
2807
        }
2808

2809
        /**
2810
         * {@inheritDoc}
2811
         */
2812
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2813
            return new ForMismatchedType<U, V>(property, value);
1✔
2814
        }
2815

2816
        /**
2817
         * {@inheritDoc}
2818
         */
2819
        public U resolve() {
2820
            throw new IllegalStateException(value + " cannot be used as value for " + property);
×
2821
        }
2822

2823
        /**
2824
         * {@inheritDoc}
2825
         */
2826
        public AnnotationValue.Loaded<V> load(@MaybeNull ClassLoader classLoader) {
2827
            try {
2828
                Class<?> type = Class.forName(property.getDeclaringType().getName(), false, classLoader);
1✔
2829
                try {
2830
                    return new Loaded<V>(type.getMethod(property.getName()), value);
1✔
2831
                } catch (NoSuchMethodException exception) {
×
2832
                    return new ForIncompatibleType.Loaded<V>(type);
×
2833
                }
2834
            } catch (ClassNotFoundException exception) {
×
2835
                return new ForMissingType.Loaded<V>(property.getDeclaringType().getName(), exception);
×
2836
            }
2837
        }
2838

2839
        /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
2840

2841
        @Override
2842
        public String toString() {
2843
            return "/* Warning type mismatch! \"" + value + "\" */";
×
2844
        }
2845

2846
        /**
2847
         * Describes an annotation value for a property that is not assignable to it.
2848
         *
2849
         * @param <W> The type of the annotation's expected value.
2850
         */
2851
        public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<W> {
2852

2853
            /**
2854
             * The annotation property that is not well-defined.
2855
             */
2856
            private final Method property;
2857

2858
            /**
2859
             * A value description of the incompatible property or {@code null}.
2860
             */
2861
            private final String value;
2862

2863
            /**
2864
             * Creates a new loaded version of a property with an incompatible type.
2865
             *
2866
             * @param property The annotation property that is not well-defined.
2867
             * @param value    A value description of the incompatible property or {@code null}.
2868
             */
2869
            public Loaded(Method property, String value) {
1✔
2870
                this.property = property;
1✔
2871
                this.value = value;
1✔
2872
            }
1✔
2873

2874
            /**
2875
             * {@inheritDoc}
2876
             */
2877
            public W resolve() {
2878
                throw new AnnotationTypeMismatchException(property, value);
1✔
2879
            }
2880

2881
            @Override
2882
            public String toString() {
2883
                return "/* Warning type mismatch! \"" + value + "\" */";
×
2884
            }
2885
        }
2886
    }
2887

2888
    /**
2889
     * Represents a missing annotation property which is not represented by a default value.
2890
     *
2891
     * @param <U> The type of the annotation's value when it is not loaded.
2892
     * @param <V> The type of the annotation's value when it is loaded.
2893
     */
2894
    class ForMissingValue<U, V> extends AnnotationValue.AbstractBase<U, V> {
2895

2896
        /**
2897
         * The annotation type for which a property is not defined.
2898
         */
2899
        private final TypeDescription typeDescription;
2900

2901
        /**
2902
         * The name of the property without an annotation value.
2903
         */
2904
        private final String property;
2905

2906
        /**
2907
         * Creates a new missing annotation value.
2908
         *
2909
         * @param typeDescription The annotation type for which a property is not defined.
2910
         * @param property        The name of the property without an annotation value.
2911
         */
2912
        public ForMissingValue(TypeDescription typeDescription, String property) {
1✔
2913
            this.typeDescription = typeDescription;
1✔
2914
            this.property = property;
1✔
2915
        }
1✔
2916

2917
        /**
2918
         * {@inheritDoc}
2919
         */
2920
        public State getState() {
2921
            return State.UNDEFINED;
1✔
2922
        }
2923

2924
        /**
2925
         * {@inheritDoc}
2926
         */
2927
        public Sort getSort() {
2928
            return Sort.NONE;
×
2929
        }
2930

2931
        /**
2932
         * {@inheritDoc}
2933
         */
2934
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
2935
            return this;
×
2936
        }
2937

2938
        /**
2939
         * {@inheritDoc}
2940
         */
2941
        @SuppressWarnings("unchecked")
2942
        public AnnotationValue.Loaded<V> load(@MaybeNull ClassLoader classLoader) {
2943
            try {
2944
                Class<? extends Annotation> type = (Class<? extends Annotation>) Class.forName(typeDescription.getName(), false, classLoader);
1✔
2945
                return type.isAnnotation()
1✔
2946
                        ? new Loaded<V>(type, property)
2947
                        : new ForIncompatibleType.Loaded<V>(type);
2948
            } catch (ClassNotFoundException exception) {
×
2949
                return new ForMissingType.Loaded<V>(typeDescription.getName(), exception);
×
2950
            }
2951
        }
2952

2953
        /**
2954
         * {@inheritDoc}
2955
         */
2956
        public U resolve() {
2957
            throw new IllegalStateException(typeDescription + " does not define " + property);
×
2958
        }
2959

2960
        /* does not implement hashCode and equals method to mimic OpenJDK behavior. Does never appear in toString methods. */
2961

2962
        /**
2963
         * Describes an annotation value for a property that is not assignable to it.
2964
         *
2965
         * @param <W> The type of the annotation's expected value.
2966
         */
2967
        public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase<W> {
2968

2969
            /**
2970
             * The annotation type.
2971
             */
2972
            private final Class<? extends Annotation> type;
2973

2974
            /**
2975
             * The name of the property for which the annotation value is missing.
2976
             */
2977
            private final String property;
2978

2979
            /**
2980
             * Creates a new loaded representation for an unresolved property.
2981
             *
2982
             * @param type     The annotation type.
2983
             * @param property The name of the property for which the annotation value is missing.
2984
             */
2985
            public Loaded(Class<? extends Annotation> type, String property) {
1✔
2986
                this.type = type;
1✔
2987
                this.property = property;
1✔
2988
            }
1✔
2989

2990
            /**
2991
             * {@inheritDoc}
2992
             */
2993
            public State getState() {
2994
                return State.UNDEFINED;
×
2995
            }
2996

2997
            /**
2998
             * {@inheritDoc}
2999
             */
3000
            public W resolve() {
3001
                throw new IncompleteAnnotationException(type, property);
1✔
3002
            }
3003

3004
            /**
3005
             * {@inheritDoc}
3006
             */
3007
            public boolean represents(Object value) {
3008
                return false;
×
3009
            }
3010

3011
            /* does not implement hashCode and equals method to mimic OpenJDK behavior. Does never appear in toString methods. */
3012
        }
3013
    }
3014

3015
    /**
3016
     * Represents an annotation value where its declared type does not fulfil an expectation.
3017
     *
3018
     * @param <U> The type of the annotation's value when it is not loaded.
3019
     * @param <V> The type of the annotation's value when it is loaded.
3020
     */
3021
    class ForIncompatibleType<U, V> extends AnnotationValue.AbstractBase<U, V> {
3022

3023
        /**
3024
         * A description of the type that does not fulfil an expectation.
3025
         */
3026
        private final TypeDescription typeDescription;
3027

3028
        /**
3029
         * Creates a new description for an annotation value that does not fulfil expectations.
3030
         *
3031
         * @param typeDescription A description of the type that does not fulfil the expectations.
3032
         */
3033
        public ForIncompatibleType(TypeDescription typeDescription) {
×
3034
            this.typeDescription = typeDescription;
×
3035
        }
×
3036

3037
        /**
3038
         * {@inheritDoc}
3039
         */
3040
        public State getState() {
3041
            return State.UNRESOLVED;
×
3042
        }
3043

3044
        /**
3045
         * {@inheritDoc}
3046
         */
3047
        public Sort getSort() {
3048
            return Sort.NONE;
×
3049
        }
3050

3051
        /**
3052
         * {@inheritDoc}
3053
         */
3054
        public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
3055
            return this;
×
3056
        }
3057

3058
        /**
3059
         * {@inheritDoc}
3060
         */
3061
        public U resolve() {
3062
            throw new IllegalStateException("Property is defined with an incompatible runtime type: " + typeDescription);
×
3063
        }
3064

3065
        /**
3066
         * {@inheritDoc}
3067
         */
3068
        public AnnotationValue.Loaded<V> load(@MaybeNull ClassLoader classLoader) {
3069
            try {
3070
                return new Loaded<V>(Class.forName(typeDescription.getName(), false, classLoader));
×
3071
            } catch (ClassNotFoundException exception) {
×
3072
                return new ForMissingType.Loaded<V>(typeDescription.getName(), exception);
×
3073
            }
3074
        }
3075

3076
        /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
3077

3078
        @Override
3079
        public String toString() {
3080
            return "/* Warning type incompatibility! \"" + typeDescription.getName() + "\" */";
×
3081
        }
3082

3083
        /**
3084
         * A description of annotation value for a type that does not fulfil an expectation.
3085
         *
3086
         * @param <W> The type of the annotation's expected value.
3087
         */
3088
        public static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase.ForUnresolvedProperty<W> {
3089

3090
            /**
3091
             * The type that does not fulfil an expectation.
3092
             */
3093
            private final Class<?> type;
3094

3095
            /**
3096
             * Creates a new description of an annotation.
3097
             *
3098
             * @param type The type that does not fulfil an expectation.
3099
             */
3100
            public Loaded(Class<?> type) {
×
3101
                this.type = type;
×
3102
            }
×
3103

3104
            /**
3105
             * {@inheritDoc}
3106
             */
3107
            public W resolve() {
3108
                throw new IncompatibleClassChangeError(type.toString());
×
3109
            }
3110

3111
            /* does not implement hashCode and equals method to mimic OpenJDK behavior. */
3112

3113
            @Override
3114
            public String toString() {
3115
                return "/* Warning type incompatibility! \"" + type.getName() + "\" */";
×
3116
            }
3117
        }
3118
    }
3119
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc