package net.bytebuddy.description.modifier; import lombok.EqualsAndHashCode; import org.objectweb.asm.Opcodes; import java.util.Arrays; import java.util.Collection; /** * An element that describes a type modifier as described in the * <a href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html">JVMS</a>. * <p> </p> * This allows for a more expressive and type safe alternative of defining a type's or type member's modifiers. * However, note that modifier's that apply competing modifiers (such as {@code private} and {@code protected} * should not be combined and will result in invalid types. An exception is thrown when built-in modifiers that * cannot be combined are used together. */ public interface ModifierContributor { /** * The empty modifier. */ int EMPTY_MASK = 0; /** * Returns the mask of this modifier. * * @return The modifier mask that is to be applied to the target type or type member. */ int getMask(); /** * Returns the entire range of modifiers that address this contributor's property. * * @return The range of this contributor's property. */ int getRange(); /** * Determines if this is the default modifier. * * @return {@code true} if this contributor represents the default modifier. */ boolean isDefault(); /** * A marker interface for modifiers that can be applied to types. */ interface ForType extends ModifierContributor { /** * A mask for all legal modifiers of a Java type. */ int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC; } /** * A marker interface for modifiers that can be applied to fields. */ interface ForField extends ModifierContributor { /** * A mask for all legal modifiers of a Java field. */ int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_DEPRECATED | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE; } /** * A marker interface for modifiers that can be applied to methods. */ interface ForMethod extends ModifierContributor { /** * A mask for all legal modifiers of a Java method. */ int MASK = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_FINAL | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_STRICT | Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_VARARGS; } /** * A marker interface for modifiers that can be applied to method parameters. */ interface ForParameter extends ModifierContributor { /** * A mask for all legal modifiers of a Java parameter. */ int MASK = Opcodes.ACC_MANDATED | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC; } /** * A resolver for Java modifiers represented by {@link ModifierContributor}s. * * @param <T> The type of the {@link ModifierContributor}s being resolved. */ @EqualsAndHashCode class Resolver<T extends ModifierContributor> { /** * The modifier contributors to resolve. */ private final Collection<? extends T> modifierContributors; /** * Creates a new resolver. * * @param modifierContributors The modifier contributors to resolve. */ protected Resolver(Collection<? extends T> modifierContributors) { this.modifierContributors = modifierContributors; } /** * Creates a new resolver for modifier contributors to a type. * * @param modifierContributor The modifier contributors to resolve. * @return A resolver for the provided modifier contributors. */ public static Resolver<ForType> of(ForType... modifierContributor) { return of(Arrays.asList(modifierContributor)); } /** * Creates a new resolver for modifier contributors to a field. * * @param modifierContributor The modifier contributors to resolve. * @return A resolver for the provided modifier contributors. */ public static Resolver<ForField> of(ForField... modifierContributor) { return of(Arrays.asList(modifierContributor)); } /** * Creates a new resolver for modifier contributors to a method. * * @param modifierContributor The modifier contributors to resolve. * @return A resolver for the provided modifier contributors. */ public static Resolver<ForMethod> of(ForMethod... modifierContributor) { return of(Arrays.asList(modifierContributor)); } /** * Creates a new resolver for modifier contributors to a parameter. * * @param modifierContributor The modifier contributors to resolve. * @return A resolver for the provided modifier contributors. */ public static Resolver<ForParameter> of(ForParameter... modifierContributor) { return Resolver.of(Arrays.asList(modifierContributor)); } /** * Creates a new resolver for any modifier contributor of a given type. * * @param modifierContributors The modifier contributors to resolve. * @param <S> The modifier contributors type. * @return A resolver for the provided modifier contributors. */ public static <S extends ModifierContributor> Resolver<S> of(Collection<? extends S> modifierContributors) { return new Resolver<S>(modifierContributors); } /** * Resolves the modifier contributors based on a zero modifier. * * @return The resolved modifiers. */ public int resolve() { return resolve(EMPTY_MASK); } /** * Resolves the modifier contributors based on a given modifier. * * @param modifiers The base modifiers. * @return The resolved modifiers. */ public int resolve(int modifiers) { for (T modifierContributor : modifierContributors) { modifiers = (modifiers & ~modifierContributor.getRange()) | modifierContributor.getMask(); } return modifiers; } } }