1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.bytebuddy.implementation.attribute;
17
18 import net.bytebuddy.description.annotation.AnnotationDescription;
19 import net.bytebuddy.description.field.FieldDescription;
20 import net.bytebuddy.description.method.MethodDescription;
21 import net.bytebuddy.description.type.RecordComponentDescription;
22 import net.bytebuddy.description.type.TypeDescription;
23
24 /**
25 * An annotation value filter is responsible for determining which values should be skipped and rather be represented as an
26 * annotation type's default values when writing an annotation to a class file.
27 */
28 public interface AnnotationValueFilter {
29
30 /**
31 * Checks if the given annotation value should be written as the value of the provided annotation property.
32 *
33 * @param annotationDescription The annotation value that is being written.
34 * @param methodDescription The annotation method of which a value is being written.
35 * @return {@code true} if the value should be written to the annotation.
36 */
37 boolean isRelevant(AnnotationDescription annotationDescription, MethodDescription.InDefinedShape methodDescription);
38
39 /**
40 * A factory for creating an annotation value filter for an annotation's target.
41 */
42 interface Factory {
43
44 /**
45 * Creates an annotation value filter for writing annotations on an instrumented type.
46 *
47 * @param instrumentedType The instrumented type onto which the annotations are written.
48 * @return An annotation value filter to be used when writing annotations onto the given type.
49 */
50 AnnotationValueFilter on(TypeDescription instrumentedType);
51
52 /**
53 * Creates an annotation value filter for writing annotations on a field.
54 *
55 * @param fieldDescription The field onto which the annotations are written.
56 * @return An annotation value filter to be used when writing annotations onto the given field.
57 */
58 AnnotationValueFilter on(FieldDescription fieldDescription);
59
60 /**
61 * Creates an annotation value filter for writing annotations on a method.
62 *
63 * @param methodDescription The method onto which the annotations are written.
64 * @return An annotation value filter to be used when writing annotations onto the given method.
65 */
66 AnnotationValueFilter on(MethodDescription methodDescription);
67
68 /**
69 * Creates an annotation value filter for writing annotations on a record component.
70 *
71 * @param recordComponentDescription The record component onto which the annotations are written.
72 * @return An annotation value filter to be used when writing annotations onto the given record component.
73 */
74 AnnotationValueFilter on(RecordComponentDescription recordComponentDescription);
75 }
76
77 /**
78 * A default implementation of an annotation value filter that applies the same strategy for any type, field or method.
79 */
80 enum Default implements AnnotationValueFilter, Factory {
81
82 /**
83 * An annotation value filter where default values are skipped and not included in the class file.
84 */
85 SKIP_DEFAULTS {
86 /** {@inheritDoc} */
87 public boolean isRelevant(AnnotationDescription annotationDescription, MethodDescription.InDefinedShape methodDescription) {
88 Object defaultValue = methodDescription.getDefaultValue();
89 return defaultValue == null || !defaultValue.equals(annotationDescription.getValue(methodDescription));
90 }
91 },
92
93 /**
94 * An annotation value filter where default values are included in the class file.
95 */
96 APPEND_DEFAULTS {
97 /** {@inheritDoc} */
98 public boolean isRelevant(AnnotationDescription annotationDescription, MethodDescription.InDefinedShape methodDescription) {
99 return true;
100 }
101 };
102
103 /**
104 * {@inheritDoc}
105 */
106 public AnnotationValueFilter on(TypeDescription instrumentedType) {
107 return this;
108 }
109
110 /**
111 * {@inheritDoc}
112 */
113 public AnnotationValueFilter on(FieldDescription fieldDescription) {
114 return this;
115 }
116
117 /**
118 * {@inheritDoc}
119 */
120 public AnnotationValueFilter on(MethodDescription methodDescription) {
121 return this;
122 }
123
124 /**
125 * {@inheritDoc}
126 */
127 public AnnotationValueFilter on(RecordComponentDescription recordComponentDescription) {
128 return this;
129 }
130 }
131 }
132