1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.description.modifier;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.jar.asm.Opcodes;
20
21 import java.util.Arrays;
22 import java.util.Collection;
23
24 /**
25  * An element that describes a type modifier as described in the
26  * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html">JVMS</a>.
27  * <p>&nbsp;</p>
28  * This allows for a more expressive and type safe alternative of defining a type's or type member's modifiers.
29  * However, note that modifier's that apply competing modifiers (such as {@code private} and {@code protected}
30  * should not be combined and will result in invalid types. An exception is thrown when built-in modifiers that
31  * cannot be combined are used together.
32  */

33 public interface ModifierContributor {
34
35     /**
36      * The empty modifier.
37      */

38     int EMPTY_MASK = 0;
39
40     /**
41      * Returns the mask of this modifier.
42      *
43      * @return The modifier mask that is to be applied to the target type or type member.
44      */

45     int getMask();
46
47     /**
48      * Returns the entire range of modifiers that address this contributor's property.
49      *
50      * @return The range of this contributor's property.
51      */

52     int getRange();
53
54     /**
55      * Determines if this is the default modifier.
56      *
57      * @return {@code trueif this contributor represents the default modifier.
58      */

59     boolean isDefault();
60
61     /**
62      * A marker interface for modifiers that can be applied to types.
63      */

64     interface ForType extends ModifierContributor {
65
66         /**
67          * A mask for all legal modifiers of a Java type.
68          */

69         int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC
70                 | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_DEPRECATED
71                 | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC;
72     }
73
74     /**
75      * A marker interface for modifiers that can be applied to fields.
76      */

77     interface ForField extends ModifierContributor {
78
79         /**
80          * A mask for all legal modifiers of a Java field.
81          */

82         int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE
83                 | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC
84                 | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE;
85     }
86
87     /**
88      * A marker interface for modifiers that can be applied to methods.
89      */

90     interface ForMethod extends ModifierContributor {
91
92         /**
93          * A mask for all legal modifiers of a Java method.
94          */

95         int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC
96                 | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT
97                 | Opcodes.ACC_STATIC | Opcodes.ACC_STRICT | Opcodes.ACC_SYNCHRONIZED
98                 | Opcodes.ACC_VARARGS;
99     }
100
101     /**
102      * A marker interface for modifiers that can be applied to method parameters.
103      */

104     interface ForParameter extends ModifierContributor {
105
106         /**
107          * A mask for all legal modifiers of a Java parameter.
108          */

109         int MASK = Opcodes.ACC_MANDATED | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
110
111     }
112
113     /**
114      * A resolver for Java modifiers represented by {@link ModifierContributor}s.
115      *
116      * @param <T> The type of the {@link ModifierContributor}s being resolved.
117      */

118     @HashCodeAndEqualsPlugin.Enhance
119     class Resolver<T extends ModifierContributor> {
120
121         /**
122          * The modifier contributors to resolve.
123          */

124         private final Collection<? extends T> modifierContributors;
125
126         /**
127          * Creates a new resolver.
128          *
129          * @param modifierContributors The modifier contributors to resolve.
130          */

131         protected Resolver(Collection<? extends T> modifierContributors) {
132             this.modifierContributors = modifierContributors;
133         }
134
135         /**
136          * Creates a new resolver for modifier contributors to a type.
137          *
138          * @param modifierContributor The modifier contributors to resolve.
139          * @return A resolver for the provided modifier contributors.
140          */

141         public static Resolver<ForType> of(ForType... modifierContributor) {
142             return of(Arrays.asList(modifierContributor));
143         }
144
145         /**
146          * Creates a new resolver for modifier contributors to a field.
147          *
148          * @param modifierContributor The modifier contributors to resolve.
149          * @return A resolver for the provided modifier contributors.
150          */

151         public static Resolver<ForField> of(ForField... modifierContributor) {
152             return of(Arrays.asList(modifierContributor));
153         }
154
155         /**
156          * Creates a new resolver for modifier contributors to a method.
157          *
158          * @param modifierContributor The modifier contributors to resolve.
159          * @return A resolver for the provided modifier contributors.
160          */

161         public static Resolver<ForMethod> of(ForMethod... modifierContributor) {
162             return of(Arrays.asList(modifierContributor));
163         }
164
165         /**
166          * Creates a new resolver for modifier contributors to a parameter.
167          *
168          * @param modifierContributor The modifier contributors to resolve.
169          * @return A resolver for the provided modifier contributors.
170          */

171         public static Resolver<ForParameter> of(ForParameter... modifierContributor) {
172             return Resolver.of(Arrays.asList(modifierContributor));
173         }
174
175         /**
176          * Creates a new resolver for any modifier contributor of a given type.
177          *
178          * @param modifierContributors The modifier contributors to resolve.
179          * @param <S>                  The modifier contributors type.
180          * @return A resolver for the provided modifier contributors.
181          */

182         public static <S extends ModifierContributor> Resolver<S> of(Collection<? extends S> modifierContributors) {
183             return new Resolver<S>(modifierContributors);
184         }
185
186         /**
187          * Resolves the modifier contributors based on a zero modifier.
188          *
189          * @return The resolved modifiers.
190          */

191         public int resolve() {
192             return resolve(EMPTY_MASK);
193         }
194
195         /**
196          * Resolves the modifier contributors based on a given modifier.
197          *
198          * @param modifiers The base modifiers.
199          * @return The resolved modifiers.
200          */

201         public int resolve(int modifiers) {
202             for (T modifierContributor : modifierContributors) {
203                 modifiers = (modifiers & ~modifierContributor.getRange()) | modifierContributor.getMask();
204             }
205             return modifiers;
206         }
207     }
208 }
209