All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testifyproject.bytebuddy.implementation.bind.annotation.FieldValue Maven / Gradle / Ivy

The newest version!
package org.testifyproject.bytebuddy.implementation.bind.annotation;

import org.testifyproject.bytebuddy.description.annotation.AnnotationDescription;
import org.testifyproject.bytebuddy.description.field.FieldDescription;
import org.testifyproject.bytebuddy.description.method.MethodDescription;
import org.testifyproject.bytebuddy.description.method.MethodList;
import org.testifyproject.bytebuddy.description.method.ParameterDescription;
import org.testifyproject.bytebuddy.description.type.TypeDescription;
import org.testifyproject.bytebuddy.implementation.Implementation;
import org.testifyproject.bytebuddy.implementation.bind.MethodDelegationBinder;
import org.testifyproject.bytebuddy.implementation.bytecode.StackManipulation;
import org.testifyproject.bytebuddy.implementation.bytecode.assign.Assigner;
import org.testifyproject.bytebuddy.implementation.bytecode.member.FieldAccess;
import org.testifyproject.bytebuddy.implementation.bytecode.member.MethodVariableAccess;

import java.lang.annotation.*;

import static org.testifyproject.bytebuddy.matcher.ElementMatchers.named;

/**
 * 

* Assigns the value of a field of the instrumented type to the annotated parameter. For a binding to be valid, * the instrumented type must be able to access a field of the given name. Also, the parameter's type must be * assignable to the given field. For attempting a type casting, the {@link RuntimeType} annotation can be * applied to the parameter. *

*

* Setting {@link FieldValue#value()} is optional. If the value is not set, the field value attempts to bind a setter's * or getter's field if the intercepted method is an accessor method. Otherwise, the binding renders the target method * to be an illegal candidate for binding. *

* * @see org.testifyproject.bytebuddy.implementation.MethodDelegation * @see org.testifyproject.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder * @see org.testifyproject.bytebuddy.implementation.bind.annotation.RuntimeType */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface FieldValue { /** * The name of the field to be accessed. * * @return The name of the field. */ String value() default TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFieldBinding.BEAN_PROPERTY; /** * Defines the type on which the field is declared. If this value is not set, the most specific type's field is read, * if two fields with the same name exist in the same type hierarchy. * * @return The type that declares the accessed field. */ Class declaringType() default void.class; /** * Binds a {@link FieldValue} annotation. */ enum Binder implements TargetMethodAnnotationDrivenBinder.ParameterBinder { /** * The singleton instance. */ INSTANCE(new Delegate()); /** * The annotation method that for the defining type. */ private static final MethodDescription.InDefinedShape DECLARING_TYPE; /** * The annotation method for the field's name. */ private static final MethodDescription.InDefinedShape FIELD_NAME; /* * Initializes the methods of the annotation that is read by this binder. */ static { MethodList methodList = new TypeDescription.ForLoadedType(FieldValue.class).getDeclaredMethods(); DECLARING_TYPE = methodList.filter(named("declaringType")).getOnly(); FIELD_NAME = methodList.filter(named("value")).getOnly(); } /** * A delegate parameter binder responsible for binding the parameter. */ private final TargetMethodAnnotationDrivenBinder.ParameterBinder delegate; /** * Creates a new binder for a {@link FieldValue}. * * @param delegate A delegate parameter binder responsible for binding the parameter. */ Binder(TargetMethodAnnotationDrivenBinder.ParameterBinder delegate) { this.delegate = delegate; } @Override public Class getHandledType() { return delegate.getHandledType(); } @Override public MethodDelegationBinder.ParameterBinding bind(AnnotationDescription.Loadable annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { return delegate.bind(annotation, source, target, implementationTarget, assigner, typing); } /** * A delegate implementation for the {@link FieldValue.Binder}. */ protected static class Delegate extends ForFieldBinding { @Override public Class getHandledType() { return FieldValue.class; } @Override protected MethodDelegationBinder.ParameterBinding bind(FieldDescription fieldDescription, AnnotationDescription.Loadable annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner) { StackManipulation stackManipulation = new StackManipulation.Compound( fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read(), assigner.assign(fieldDescription.getType(), target.getType(), RuntimeType.Verifier.check(target)) ); return stackManipulation.isValid() ? new MethodDelegationBinder.ParameterBinding.Anonymous(stackManipulation) : MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } @Override protected String fieldName(AnnotationDescription.Loadable annotation) { return annotation.getValue(FIELD_NAME).resolve(String.class); } @Override protected TypeDescription declaringType(AnnotationDescription.Loadable annotation) { return annotation.getValue(DECLARING_TYPE).resolve(TypeDescription.class); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy