// Generated by delombok at Sun Feb 26 12:31:38 KST 2017 package scouter.bytebuddy.implementation.bind.annotation; import scouter.bytebuddy.description.annotation.AnnotationDescription; import scouter.bytebuddy.description.field.FieldDescription; import scouter.bytebuddy.description.method.MethodDescription; import scouter.bytebuddy.description.method.ParameterDescription; import scouter.bytebuddy.description.type.TypeDescription; import scouter.bytebuddy.dynamic.scaffold.FieldLocator; import scouter.bytebuddy.implementation.Implementation; import scouter.bytebuddy.implementation.MethodDelegation; import scouter.bytebuddy.implementation.bind.MethodDelegationBinder; import scouter.bytebuddy.implementation.bytecode.StackManipulation; import scouter.bytebuddy.implementation.bytecode.assign.Assigner; import scouter.bytebuddy.implementation.bytecode.constant.*; import scouter.bytebuddy.utility.JavaConstant; import scouter.bytebuddy.utility.JavaType; import java.lang.annotation.Annotation; import java.util.*; import static scouter.bytebuddy.matcher.ElementMatchers.isGetter; import static scouter.bytebuddy.matcher.ElementMatchers.isSetter; /** * This {@link MethodDelegationBinder} binds * method by analyzing annotations found on the <i>target</i> method that is subject to a method binding. */ public class TargetMethodAnnotationDrivenBinder implements MethodDelegationBinder { /** * The processor for performing an actual method delegation. */ private final DelegationProcessor delegationProcessor; /** * Creates a new target method annotation-driven binder. * * @param delegationProcessor The delegation proessor to use. */ protected TargetMethodAnnotationDrivenBinder(DelegationProcessor delegationProcessor) { this.delegationProcessor = delegationProcessor; } /** * Creates a new method delegation binder that binds method based on annotations found on the target method. * * @param parameterBinders A list of parameter binder delegates. Each such delegate is responsible for creating a * {@link MethodDelegationBinder.ParameterBinding} * for a specific annotation. * @return An appropriate method delegation binder. */ public static MethodDelegationBinder of(List<? extends ParameterBinder<?>> parameterBinders) { return new TargetMethodAnnotationDrivenBinder(DelegationProcessor.of(parameterBinders)); } @Override public MethodDelegationBinder.Record compile(MethodDescription candidate) { if (IgnoreForBinding.Verifier.check(candidate)) { return MethodDelegationBinder.Record.Illegal.INSTANCE; } List<DelegationProcessor.Handler> handlers = new ArrayList<DelegationProcessor.Handler>(candidate.getParameters().size()); for (ParameterDescription parameterDescription : candidate.getParameters()) { handlers.add(delegationProcessor.prepare(parameterDescription)); } return new Record(candidate, handlers, RuntimeType.Verifier.check(candidate)); } /** * A compiled record of a target method annotation-driven binder. */ protected static class Record implements MethodDelegationBinder.Record { /** * The candidate method. */ private final MethodDescription candidate; /** * A list of handlers for each parameter. */ private final List<DelegationProcessor.Handler> handlers; /** * The typing to apply. */ private final Assigner.Typing typing; /** * Creates a default compiled method delegation binder. * * @param candidate The candidate method. * @param handlers A list of handlers for each parameter. * @param typing The typing to apply. */ protected Record(MethodDescription candidate, List<DelegationProcessor.Handler> handlers, Assigner.Typing typing) { this.candidate = candidate; this.handlers = handlers; this.typing = typing; } @Override public MethodBinding bind(Implementation.Target implementationTarget, MethodDescription source, MethodDelegationBinder.TerminationHandler terminationHandler, MethodInvoker methodInvoker, Assigner assigner) { if (!candidate.isAccessibleTo(implementationTarget.getInstrumentedType())) { return MethodBinding.Illegal.INSTANCE; } StackManipulation methodTermination = terminationHandler.resolve(assigner, typing, source, candidate); if (!methodTermination.isValid()) { return MethodBinding.Illegal.INSTANCE; } MethodBinding.Builder methodDelegationBindingBuilder = new MethodBinding.Builder(methodInvoker, candidate); for (DelegationProcessor.Handler handler : handlers) { ParameterBinding<?> parameterBinding = handler.bind(source, implementationTarget, assigner); if (!parameterBinding.isValid() || !methodDelegationBindingBuilder.append(parameterBinding)) { return MethodBinding.Illegal.INSTANCE; } } return methodDelegationBindingBuilder.build(methodTermination); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder.Record)) return false; final TargetMethodAnnotationDrivenBinder.Record other = (TargetMethodAnnotationDrivenBinder.Record) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$candidate = this.candidate; final java.lang.Object other$candidate = other.candidate; if (this$candidate == null ? other$candidate != null : !this$candidate.equals(other$candidate)) return false; final java.lang.Object this$handlers = this.handlers; final java.lang.Object other$handlers = other.handlers; if (this$handlers == null ? other$handlers != null : !this$handlers.equals(other$handlers)) return false; final java.lang.Object this$typing = this.typing; final java.lang.Object other$typing = other.typing; if (this$typing == null ? other$typing != null : !this$typing.equals(other$typing)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder.Record; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $candidate = this.candidate; result = result * PRIME + ($candidate == null ? 43 : $candidate.hashCode()); final java.lang.Object $handlers = this.handlers; result = result * PRIME + ($handlers == null ? 43 : $handlers.hashCode()); final java.lang.Object $typing = this.typing; result = result * PRIME + ($typing == null ? 43 : $typing.hashCode()); return result; } } /** * A parameter binder is used as a delegate for binding a parameter according to a particular annotation type found * on this parameter. * * @param <T> The {@link java.lang.annotation.Annotation#annotationType()} handled by this parameter binder. */ public interface ParameterBinder<T extends Annotation> { /** * The default parameter binders to be used. */ List<ParameterBinder<?>> DEFAULTS = Collections.unmodifiableList(Arrays.<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>>asList(Argument.Binder.INSTANCE, AllArguments.Binder.INSTANCE, Origin.Binder.INSTANCE, This.Binder.INSTANCE, Super.Binder.INSTANCE, Default.Binder.INSTANCE, SuperCall.Binder.INSTANCE, DefaultCall.Binder.INSTANCE, SuperMethod.Binder.INSTANCE, DefaultMethod.Binder.INSTANCE, FieldValue.Binder.INSTANCE, StubValue.Binder.INSTANCE, Empty.Binder.INSTANCE)); /** * The annotation type that is handled by this parameter binder. * * @return The {@link java.lang.annotation.Annotation#annotationType()} handled by this parameter binder. */ Class<T> getHandledType(); /** * Creates a parameter binding for the given target parameter. * * @param annotation The annotation that was cause for the delegation to this argument binder. * @param source The intercepted source method. * @param target Tge target parameter that is subject to be bound to * intercepting the {@code source} method. * @param implementationTarget The target of the current implementation that is subject to this binding. * @param assigner An assigner that can be used for applying the binding. * @param typing The typing to apply. * @return A parameter binding for the requested target method parameter. */ ParameterBinding<?> bind(AnnotationDescription.Loadable<T> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing); /** * <p> * Implements a parameter binder that binds a fixed value to a parameter with a given annotation. * </p> * <p> * This binder is only capable to store values that can either be expressed as Java byte code or as a constant pool value. This * includes primitive types, {@link String} values, {@link Class} values which can also be expressed as {@link TypeDescription} * instances or method handles and method types for classes of a version at least of Java 7. The latter instances can also be * expressed as unloaded {@link JavaConstant} representations. * </p> * <p> * <b>Important</b>: When supplying a method handle or a method type, all types that are implied must be visible to the instrumented * type or an {@link IllegalAccessException} will be thrown at runtime. * </p> * * @param <S> The bound annotation's type. */ abstract class ForFixedValue<S extends Annotation> implements ParameterBinder<S> { @Override public ParameterBinding<?> bind(AnnotationDescription.Loadable<S> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { Object value = bind(annotation, source, target); if (value == null) { return new ParameterBinding.Anonymous(DefaultValue.of(target.getType())); } StackManipulation stackManipulation; TypeDescription suppliedType; if (value instanceof Boolean) { stackManipulation = IntegerConstant.forValue((Boolean) value); suppliedType = new TypeDescription.ForLoadedType(boolean.class); } else if (value instanceof Byte) { stackManipulation = IntegerConstant.forValue((Byte) value); suppliedType = new TypeDescription.ForLoadedType(byte.class); } else if (value instanceof Short) { stackManipulation = IntegerConstant.forValue((Short) value); suppliedType = new TypeDescription.ForLoadedType(short.class); } else if (value instanceof Character) { stackManipulation = IntegerConstant.forValue((Character) value); suppliedType = new TypeDescription.ForLoadedType(char.class); } else if (value instanceof Integer) { stackManipulation = IntegerConstant.forValue((Integer) value); suppliedType = new TypeDescription.ForLoadedType(int.class); } else if (value instanceof Long) { stackManipulation = LongConstant.forValue((Long) value); suppliedType = new TypeDescription.ForLoadedType(long.class); } else if (value instanceof Float) { stackManipulation = FloatConstant.forValue((Float) value); suppliedType = new TypeDescription.ForLoadedType(float.class); } else if (value instanceof Double) { stackManipulation = DoubleConstant.forValue((Double) value); suppliedType = new TypeDescription.ForLoadedType(double.class); } else if (value instanceof String) { stackManipulation = new TextConstant((String) value); suppliedType = TypeDescription.STRING; } else if (value instanceof Class) { stackManipulation = ClassConstant.of(new TypeDescription.ForLoadedType((Class<?>) value)); suppliedType = TypeDescription.CLASS; } else if (value instanceof TypeDescription) { stackManipulation = ClassConstant.of((TypeDescription) value); suppliedType = TypeDescription.CLASS; } else if (JavaType.METHOD_HANDLE.getTypeStub().isInstance(value)) { stackManipulation = JavaConstant.MethodHandle.ofLoaded(value).asStackManipulation(); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); } else if (value instanceof JavaConstant.MethodHandle) { stackManipulation = new JavaConstantValue((JavaConstant.MethodHandle) value); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); } else if (JavaType.METHOD_TYPE.getTypeStub().isInstance(value)) { stackManipulation = new JavaConstantValue(JavaConstant.MethodType.ofLoaded(value)); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); } else if (value instanceof JavaConstant.MethodType) { stackManipulation = new JavaConstantValue((JavaConstant.MethodType) value); suppliedType = JavaType.METHOD_HANDLE.getTypeStub(); } else { throw new IllegalStateException("Not able to save in class\'s constant pool: " + value); } return new ParameterBinding.Anonymous(new StackManipulation.Compound(stackManipulation, assigner.assign(suppliedType.asGenericType(), target.getType(), typing))); } /** * Resolves a value for the given annotation on a parameter that is processed by a {@link MethodDelegation}. * * @param annotation The annotation that triggered this binding. * @param source The method for which a delegation is currently bound. * @param target The parameter for which a value is bound. * @return The constant pool value that is bound to this parameter or {@code null} for binding this value. */ protected abstract Object bind(AnnotationDescription.Loadable<S> annotation, MethodDescription source, ParameterDescription target); /** * <p> * A parameter binder that binds a fixed value to a parameter annotation when using a {@link MethodDelegation}. * </p> * <p> * This binder is only capable to store * values that can either be expressed as Java byte code or as a constant pool value. This includes primitive types, {@link String} values, * {@link Class} values which can also be expressed as {@link TypeDescription} instances or method handles and method types for classes of * a version at least of Java 7. The latter instances can also be expressed as unloaded {@link JavaConstant} representations. * </p> * * @param <U> The bound annotation's type. */ public static class OfConstant<U extends Annotation> extends ForFixedValue<U> { /** * The type of the annotation that is bound by this binder. */ private final Class<U> type; /** * The value that is assigned to any annotated parameter. */ private final Object value; /** * Creates a binder for binding a fixed value to a parameter annotated with the given annotation. * * @param type The type of the annotation that is bound by this binder. * @param value The value that is assigned to any annotated parameter. */ protected OfConstant(Class<U> type, Object value) { this.type = type; this.value = value; } /** * Creates a binder for binding a fixed value to a given annotation. * * @param type The type of the annotation that is bound by this binder. * @param value The value that is assigned to any annotated parameter. * @param <V> The bound annotation's type. * @return A parameter binder that binds the given annotation to the supplied value. */ public static <V extends Annotation> ParameterBinder<V> of(Class<V> type, Object value) { return new OfConstant<V>(type, value); } @Override public Class<U> getHandledType() { return type; } @Override protected Object bind(AnnotationDescription.Loadable<U> annotation, MethodDescription source, ParameterDescription target) { return value; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue.OfConstant)) return false; final TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue.OfConstant<?> other = (TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue.OfConstant<?>) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$type = this.type; final java.lang.Object other$type = other.type; if (this$type == null ? other$type != null : !this$type.equals(other$type)) return false; final java.lang.Object this$value = this.value; final java.lang.Object other$value = other.value; if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue.OfConstant; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $type = this.type; result = result * PRIME + ($type == null ? 43 : $type.hashCode()); final java.lang.Object $value = this.value; result = result * PRIME + ($value == null ? 43 : $value.hashCode()); return result; } } } /** * A parameter binder that binds a field's value. * * @param <S> The {@link java.lang.annotation.Annotation#annotationType()} handled by this parameter binder. */ abstract class ForFieldBinding<S extends Annotation> implements ParameterBinder<S> { /** * Indicates that a name should be extracted from an accessor method. */ protected static final String BEAN_PROPERTY = ""; /** * Resolves a field locator for a potential accessor method. * * @param fieldLocator The field locator to use. * @param methodDescription The method description that is the potential accessor. * @return A resolution for a field locator. */ private static FieldLocator.Resolution resolveAccessor(FieldLocator fieldLocator, MethodDescription methodDescription) { String fieldName; if (isSetter().matches(methodDescription)) { fieldName = methodDescription.getInternalName().substring(3); } else if (isGetter().matches(methodDescription)) { fieldName = methodDescription.getInternalName().substring(methodDescription.getInternalName().startsWith("is") ? 2 : 3); } else { return FieldLocator.Resolution.Illegal.INSTANCE; } return fieldLocator.locate(Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1)); } @Override public ParameterBinding<?> bind(AnnotationDescription.Loadable<S> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (!declaringType(annotation).represents(void.class)) { if (declaringType(annotation).isPrimitive() || declaringType(annotation).isArray()) { throw new IllegalStateException("A primitive type or array type cannot declare a field: " + source); } else if (!implementationTarget.getInstrumentedType().isAssignableTo(declaringType(annotation))) { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } } FieldLocator fieldLocator = declaringType(annotation).represents(void.class) ? new FieldLocator.ForClassHierarchy(implementationTarget.getInstrumentedType()) : new FieldLocator.ForExactType(declaringType(annotation), implementationTarget.getInstrumentedType()); FieldLocator.Resolution resolution = fieldName(annotation).equals(BEAN_PROPERTY) ? resolveAccessor(fieldLocator, source) : fieldLocator.locate(fieldName(annotation)); return resolution.isResolved() && !(source.isStatic() && !resolution.getField().isStatic()) ? bind(resolution.getField(), annotation, source, target, implementationTarget, assigner) : ParameterBinding.Illegal.INSTANCE; } /** * Extracts the field name from an annotation. * * @param annotation The annotation from which to extract the field name. * @return The field name defined by the handled annotation. */ protected abstract String fieldName(AnnotationDescription.Loadable<S> annotation); /** * Extracts the declaring type from an annotation. * * @param annotation The annotation from which to extract the declaring type. * @return The declaring type defined by the handled annotation. */ protected abstract TypeDescription declaringType(AnnotationDescription.Loadable<S> annotation); /** * Creates a parameter binding for the given target parameter. * * @param fieldDescription The field for which this binder binds a value. * @param annotation The annotation that was cause for the delegation to this argument binder. * @param source The intercepted source method. * @param target Tge target parameter that is subject to be bound to * intercepting the {@code source} method. * @param implementationTarget The target of the current implementation that is subject to this binding. * @param assigner An assigner that can be used for applying the binding. * @return A parameter binding for the requested target method parameter. */ protected abstract ParameterBinding<?> bind(FieldDescription fieldDescription, AnnotationDescription.Loadable<S> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner); } } /** * A delegation processor is a helper class for a * {@link TargetMethodAnnotationDrivenBinder} * for performing its actual logic. By outsourcing this logic to this helper class, a cleaner implementation * can be provided. */ protected static class DelegationProcessor { /** * A map of registered annotation types to the binder that is responsible for binding a parameter * that is annotated with the given annotation. */ private final Map<? extends TypeDescription, ? extends ParameterBinder<?>> parameterBinders; /** * Creates a new delegation processor. * * @param parameterBinders A mapping of parameter binders by their handling type. */ protected DelegationProcessor(Map<? extends TypeDescription, ? extends ParameterBinder<?>> parameterBinders) { this.parameterBinders = parameterBinders; } /** * Creates a new delegation processor. * * @param parameterBinders A list of parameter binder delegates. Each such delegate is responsible for creating * a {@link MethodDelegationBinder.ParameterBinding} * for a specific annotation. * @return A corresponding delegation processor. */ protected static DelegationProcessor of(List<? extends ParameterBinder<?>> parameterBinders) { Map<TypeDescription, ParameterBinder<?>> parameterBinderMap = new HashMap<TypeDescription, ParameterBinder<?>>(); for (ParameterBinder<?> parameterBinder : parameterBinders) { if (parameterBinderMap.put(new TypeDescription.ForLoadedType(parameterBinder.getHandledType()), parameterBinder) != null) { throw new IllegalArgumentException("Attempt to bind two handlers to " + parameterBinder.getHandledType()); } } return new DelegationProcessor(parameterBinderMap); } /** * Locates a handler which is responsible for processing the given parameter. If no explicit handler can * be located, a fallback handler is provided. * * @param target The target parameter being handled. * @return A handler for processing the parameter with the given annotations. */ protected Handler prepare(ParameterDescription target) { Assigner.Typing typing = RuntimeType.Verifier.check(target); Handler handler = new Handler.Unbound(target, typing); for (AnnotationDescription annotation : target.getDeclaredAnnotations()) { ParameterBinder<?> parameterBinder = parameterBinders.get(annotation.getAnnotationType()); if (parameterBinder != null && handler.isBound()) { throw new IllegalStateException("Ambiguous binding for parameter annotated with two handled annotation types"); } else if (parameterBinder != null /* && !handler.isBound() */) { handler = Handler.Bound.of(target, parameterBinder, annotation, typing); } } return handler; } /** * A handler is responsible for processing a parameter's binding. */ protected interface Handler { /** * Indicates if this handler was explicitly bound. * * @return {@code true} if this handler was explicitly bound. */ boolean isBound(); /** * Handles a parameter binding. * * @param source The intercepted source method. * @param implementationTarget The target of the current implementation. * @param assigner The assigner to use. * @return A parameter binding that reflects the given arguments. */ ParameterBinding<?> bind(MethodDescription source, Implementation.Target implementationTarget, Assigner assigner); /** * An unbound handler is a fallback for returning an illegal binding for parameters for which no parameter * binder could be located. */ class Unbound implements Handler { /** * The target parameter being handled. */ private final ParameterDescription target; /** * The typing to apply. */ private final Assigner.Typing typing; /** * Creates a new unbound handler. * * @param target The target parameter being handled. * @param typing The typing to apply. */ protected Unbound(ParameterDescription target, Assigner.Typing typing) { this.target = target; this.typing = typing; } @Override public boolean isBound() { return false; } @Override public ParameterBinding<?> bind(MethodDescription source, Implementation.Target implementationTarget, Assigner assigner) { return Argument.Binder.INSTANCE.bind(AnnotationDescription.ForLoadedAnnotation.<Argument>of(new DefaultArgument(target.getIndex())), source, target, implementationTarget, assigner, typing); } /** * A default implementation of an {@link Argument} annotation. */ protected static class DefaultArgument implements Argument { /** * The name of the value annotation parameter. */ private static final String VALUE = "value"; /** * The name of the value binding mechanic parameter. */ private static final String BINDING_MECHANIC = "bindingMechanic"; /** * The index of the source method parameter to be bound. */ private final int parameterIndex; /** * Creates a new instance of an argument annotation. * * @param parameterIndex The index of the source method parameter to be bound. */ protected DefaultArgument(int parameterIndex) { this.parameterIndex = parameterIndex; } @Override public int value() { return parameterIndex; } @Override public BindingMechanic bindingMechanic() { return BindingMechanic.UNIQUE; } @Override public Class<Argument> annotationType() { return Argument.class; } @Override public boolean equals(Object other) { return this == other || other instanceof Argument && parameterIndex == ((Argument) other).value(); } @Override public int hashCode() { return ((127 * BINDING_MECHANIC.hashCode()) ^ BindingMechanic.UNIQUE.hashCode()) + ((127 * VALUE.hashCode()) ^ parameterIndex); } @Override public String toString() { return "@" + Argument.class.getName() + "(bindingMechanic=" + BindingMechanic.UNIQUE.toString() + ", value=" + parameterIndex + ")"; } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Unbound)) return false; final TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Unbound other = (TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Unbound) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$target = this.target; final java.lang.Object other$target = other.target; if (this$target == null ? other$target != null : !this$target.equals(other$target)) return false; final java.lang.Object this$typing = this.typing; final java.lang.Object other$typing = other.typing; if (this$typing == null ? other$typing != null : !this$typing.equals(other$typing)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Unbound; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $target = this.target; result = result * PRIME + ($target == null ? 43 : $target.hashCode()); final java.lang.Object $typing = this.typing; result = result * PRIME + ($typing == null ? 43 : $typing.hashCode()); return result; } } /** * A bound handler represents an unambiguous parameter binder that was located for a given array of * annotations. * * @param <T> The annotation type of a given handler. */ class Bound<T extends Annotation> implements Handler { /** * The target parameter being handled. */ private final ParameterDescription target; /** * The parameter binder that is actually responsible for binding the parameter. */ private final ParameterBinder<T> parameterBinder; /** * The annotation value that lead to the binding of this handler. */ private final AnnotationDescription.Loadable<T> annotation; /** * The typing to apply. */ private final Assigner.Typing typing; /** * Creates a new bound handler. * * @param target The target parameter being handled. * @param parameterBinder The parameter binder that is actually responsible for binding the parameter. * @param annotation The annotation value that lead to the binding of this handler. * @param typing The typing to apply. */ protected Bound(ParameterDescription target, ParameterBinder<T> parameterBinder, AnnotationDescription.Loadable<T> annotation, Assigner.Typing typing) { this.target = target; this.parameterBinder = parameterBinder; this.annotation = annotation; this.typing = typing; } /** * Creates a handler for a given annotation. * * @param target The target parameter being handled. * @param parameterBinder The parameter binder that should process an annotation. * @param annotation An annotation instance that can be understood by this parameter binder. * @param typing The typing to apply. * @return A handler for processing the given annotation. */ @SuppressWarnings("unchecked") protected static Handler of(ParameterDescription target, ParameterBinder<?> parameterBinder, AnnotationDescription annotation, Assigner.Typing typing) { return new Bound<Annotation>(target, (ParameterBinder<Annotation>) parameterBinder, (AnnotationDescription.Loadable<Annotation>) annotation.prepare(parameterBinder.getHandledType()), typing); } @Override public boolean isBound() { return true; } @Override public ParameterBinding<?> bind(MethodDescription source, Implementation.Target implementationTarget, Assigner assigner) { return parameterBinder.bind(annotation, source, target, implementationTarget, assigner, typing); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound)) return false; final TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound<?> other = (TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound<?>) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$target = this.target; final java.lang.Object other$target = other.target; if (this$target == null ? other$target != null : !this$target.equals(other$target)) return false; final java.lang.Object this$parameterBinder = this.parameterBinder; final java.lang.Object other$parameterBinder = other.parameterBinder; if (this$parameterBinder == null ? other$parameterBinder != null : !this$parameterBinder.equals(other$parameterBinder)) return false; final java.lang.Object this$annotation = this.annotation; final java.lang.Object other$annotation = other.annotation; if (this$annotation == null ? other$annotation != null : !this$annotation.equals(other$annotation)) return false; final java.lang.Object this$typing = this.typing; final java.lang.Object other$typing = other.typing; if (this$typing == null ? other$typing != null : !this$typing.equals(other$typing)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor.Handler.Bound; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $target = this.target; result = result * PRIME + ($target == null ? 43 : $target.hashCode()); final java.lang.Object $parameterBinder = this.parameterBinder; result = result * PRIME + ($parameterBinder == null ? 43 : $parameterBinder.hashCode()); final java.lang.Object $annotation = this.annotation; result = result * PRIME + ($annotation == null ? 43 : $annotation.hashCode()); final java.lang.Object $typing = this.typing; result = result * PRIME + ($typing == null ? 43 : $typing.hashCode()); return result; } } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor)) return false; final TargetMethodAnnotationDrivenBinder.DelegationProcessor other = (TargetMethodAnnotationDrivenBinder.DelegationProcessor) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$parameterBinders = this.parameterBinders; final java.lang.Object other$parameterBinders = other.parameterBinders; if (this$parameterBinders == null ? other$parameterBinders != null : !this$parameterBinders.equals(other$parameterBinders)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder.DelegationProcessor; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $parameterBinders = this.parameterBinders; result = result * PRIME + ($parameterBinders == null ? 43 : $parameterBinders.hashCode()); return result; } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof TargetMethodAnnotationDrivenBinder)) return false; final TargetMethodAnnotationDrivenBinder other = (TargetMethodAnnotationDrivenBinder) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$delegationProcessor = this.delegationProcessor; final java.lang.Object other$delegationProcessor = other.delegationProcessor; if (this$delegationProcessor == null ? other$delegationProcessor != null : !this$delegationProcessor.equals(other$delegationProcessor)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof TargetMethodAnnotationDrivenBinder; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $delegationProcessor = this.delegationProcessor; result = result * PRIME + ($delegationProcessor == null ? 43 : $delegationProcessor.hashCode()); return result; } }