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 trueif 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