// 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;
}
}