/*
 * Copyright 2014 - 2020 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.description.annotation;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.build.CachedReturnPlugin;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.enumeration.EnumerationDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.utility.privilege.SetAccessibleAction;

import java.lang.annotation.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.util.*;

import static net.bytebuddy.matcher.ElementMatchers.named;

An annotation description describes Annotation meta data of a class without this class being required to be loaded. All values of an annotation are therefore represented in unloaded state: An annotation can however be loaded in order to access unwrapped values. This will cause a loading of the classes of these values.
/** * An annotation description describes {@link java.lang.annotation.Annotation} meta data of a class without this class * being required to be loaded. All values of an annotation are therefore represented in unloaded state: * <ul> * <li>{@link java.lang.Class} instances are represented as {@link TypeDescription}s.</li> * <li>{@link java.lang.Enum} instances are represented as * {@link net.bytebuddy.description.enumeration.EnumerationDescription}s.</li> * <li>{@link java.lang.annotation.Annotation}s are described as * {@link AnnotationDescription}s.</li> * <li>All primitive types are represented as their wrapper types.</li> * </ul> * An annotation can however be loaded in order to access unwrapped values. This will cause a loading of the classes * of these values. */
public interface AnnotationDescription {
Indicates a nonexistent annotation in a type-safe manner.
/** * Indicates a nonexistent annotation in a type-safe manner. */
AnnotationDescription.Loadable<?> UNDEFINED = null;
Returns the value of this annotation.
Params:
  • property – The property being accessed.
Returns:The value for the supplied property.
/** * Returns the value of this annotation. * * @param property The property being accessed. * @return The value for the supplied property. */
AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property);
Returns a description of the annotation type of this annotation.
Returns:A description of the annotation type of this annotation.
/** * Returns a description of the annotation type of this annotation. * * @return A description of the annotation type of this annotation. */
TypeDescription getAnnotationType();
Links this annotation description to a given annotation type such that it can be loaded. This does not cause the values of this annotation to be loaded.
Params:
  • annotationType – The loaded annotation type of this annotation description.
Type parameters:
  • <T> – The type of the annotation.
Returns:A loadable version of this annotation description.
/** * Links this annotation description to a given annotation type such that it can be loaded. This does not cause * the values of this annotation to be loaded. * * @param annotationType The loaded annotation type of this annotation description. * @param <T> The type of the annotation. * @return A loadable version of this annotation description. */
<T extends Annotation> Loadable<T> prepare(Class<T> annotationType);
Returns this annotation's retention policy.
Returns:This annotation's retention policy.
/** * Returns this annotation's retention policy. * * @return This annotation's retention policy. */
RetentionPolicy getRetention();
Returns a set of all ElementTypes that can declare this annotation.
Returns:A set of all element types that can declare this annotation.
/** * Returns a set of all {@link ElementType}s that can declare this annotation. * * @return A set of all element types that can declare this annotation. */
Set<ElementType> getElementTypes();
Checks if this annotation is inherited.
See Also:
Returns:true if this annotation is inherited.
/** * Checks if this annotation is inherited. * * @return {@code true} if this annotation is inherited. * @see Inherited */
boolean isInherited();
Checks if this annotation is documented.
See Also:
Returns:true if this annotation is documented.
/** * Checks if this annotation is documented. * * @return {@code true} if this annotation is documented. * @see Documented */
boolean isDocumented();
An annotation description that is linked to a given loaded annotation type which allows its representation as a fully loaded instance.
Type parameters:
  • <S> – The annotation type.
/** * An annotation description that is linked to a given loaded annotation type which allows its representation * as a fully loaded instance. * * @param <S> The annotation type. */
interface Loadable<S extends Annotation> extends AnnotationDescription {
Loads this annotation description. This causes all classes referenced by the annotation value to be loaded. Without specifying a class loader, the annotation's class loader which was used to prepare this instance is used.
Returns:A loaded version of this annotation description.
/** * Loads this annotation description. This causes all classes referenced by the annotation value to be loaded. * Without specifying a class loader, the annotation's class loader which was used to prepare this instance * is used. * * @return A loaded version of this annotation description. */
S load(); }
A rendering dispatcher is responsible for resolving annotation descriptions to String representations.
/** * A rendering dispatcher is responsible for resolving annotation descriptions to {@link String} representations. */
enum RenderingDispatcher {
A rendering dispatcher for any VM previous to Java 14.
/** * A rendering dispatcher for any VM previous to Java 14. */
LEGACY_VM,
A rendering dispatcher for Java 14 onward.
/** * A rendering dispatcher for Java 14 onward. */
JAVA_14_CAPABLE_VM { @Override public void appendPrefix(StringBuilder toString, String key, int count) { if (count > 1 || !key.equals("value")) { super.appendPrefix(toString, key, count); } } };
The rendering dispatcher for the current VM.
/** * The rendering dispatcher for the current VM. */
public static final RenderingDispatcher CURRENT; /* * Initializes the rendering dispatcher. */ static { ClassFileVersion classFileVersion = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6); if (classFileVersion.isAtLeast(ClassFileVersion.JAVA_V14)) { CURRENT = RenderingDispatcher.JAVA_14_CAPABLE_VM; } else { CURRENT = RenderingDispatcher.LEGACY_VM; } }
Appends the key property prefix to a string builder representing an annotation's string representation.
Params:
  • toString – The Object.toString() representation of the annotation being handled.
  • key – The key's name.
  • count – The property count.
/** * Appends the key property prefix to a string builder representing an annotation's string representation. * * @param toString The {@link Object#toString()} representation of the annotation being handled. * @param key The key's name. * @param count The property count. */
public void appendPrefix(StringBuilder toString, String key, int count) { toString.append(key).append('='); } }
An InvocationHandler for implementing annotations.
Type parameters:
  • <T> – The type of the handled annotation.
/** * An {@link java.lang.reflect.InvocationHandler} for implementing annotations. * * @param <T> The type of the handled annotation. */
class AnnotationInvocationHandler<T extends Annotation> implements InvocationHandler {
The name of the Object.hashCode() method.
/** * The name of the {@link Object#hashCode()} method. */
private static final String HASH_CODE = "hashCode";
The name of the Object.equals(Object) method.
/** * The name of the {@link Object#equals(Object)} method. */
private static final String EQUALS = "equals";
The name of the Object.toString() method.
/** * The name of the {@link Object#toString()} method. */
private static final String TO_STRING = "toString";
An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
/** * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call. */
private static final Object[] NO_ARGUMENTS = new Object[0];
The loaded annotation type.
/** * The loaded annotation type. */
private final Class<? extends Annotation> annotationType;
A sorted list of values of this annotation.
/** * A sorted list of values of this annotation. */
private final LinkedHashMap<Method, AnnotationValue.Loaded<?>> values;
Creates a new invocation handler.
Params:
  • annotationType – The loaded annotation type.
  • values – A sorted list of values of this annotation.
/** * Creates a new invocation handler. * * @param annotationType The loaded annotation type. * @param values A sorted list of values of this annotation. */
protected AnnotationInvocationHandler(Class<T> annotationType, LinkedHashMap<Method, AnnotationValue.Loaded<?>> values) { this.annotationType = annotationType; this.values = values; }
Creates a proxy instance for the supplied annotation type and values.
Params:
  • classLoader – The class loader that should be used for loading the annotation's values.
  • annotationType – The annotation's type.
  • values – The values that the annotation contains.
Type parameters:
  • <S> – The type of the handled annotation.
Returns:A proxy for the annotation type and values.
/** * Creates a proxy instance for the supplied annotation type and values. * * @param classLoader The class loader that should be used for loading the annotation's values. * @param annotationType The annotation's type. * @param values The values that the annotation contains. * @param <S> The type of the handled annotation. * @return A proxy for the annotation type and values. */
@SuppressWarnings("unchecked") public static <S extends Annotation> S of(ClassLoader classLoader, Class<S> annotationType, Map<String, ? extends AnnotationValue<?, ?>> values) { LinkedHashMap<Method, AnnotationValue.Loaded<?>> loadedValues = new LinkedHashMap<Method, AnnotationValue.Loaded<?>>(); for (Method method : annotationType.getDeclaredMethods()) { AnnotationValue<?, ?> annotationValue = values.get(method.getName()); if (annotationValue == null) { Object defaultValue = method.getDefaultValue(); loadedValues.put(method, (defaultValue == null ? new AnnotationValue.ForMissingValue<Void, Void>(new TypeDescription.ForLoadedType(method.getDeclaringClass()), method.getName()) : AnnotationDescription.ForLoadedAnnotation.asValue(defaultValue, method.getReturnType())).load(classLoader)); } else { loadedValues.put(method, annotationValue.filter(new MethodDescription.ForLoadedMethod(method)).load(classLoader)); } } return (S) Proxy.newProxyInstance(classLoader, new Class<?>[]{annotationType}, new AnnotationInvocationHandler<S>(annotationType, loadedValues)); }
{@inheritDoc}
/** * {@inheritDoc} */
public Object invoke(Object proxy, Method method, Object[] argument) { if (method.getDeclaringClass() != annotationType) { if (method.getName().equals(HASH_CODE)) { return hashCodeRepresentation(); } else if (method.getName().equals(EQUALS) && method.getParameterTypes().length == 1) { return equalsRepresentation(proxy, argument[0]); } else if (method.getName().equals(TO_STRING)) { return toStringRepresentation(); } else /* if (method.getName().equals("annotationType")) */ { return annotationType; } } return values.get(method).resolve(); }
Returns the string representation of the represented annotation.
Returns:The string representation of the represented annotation.
/** * Returns the string representation of the represented annotation. * * @return The string representation of the represented annotation. */
protected String toStringRepresentation() { StringBuilder toString = new StringBuilder(); toString.append('@'); toString.append(annotationType.getName()); toString.append('('); boolean firstMember = true; for (Map.Entry<Method, AnnotationValue.Loaded<?>> entry : values.entrySet()) { if (!entry.getValue().getState().isDefined()) { continue; } if (firstMember) { firstMember = false; } else { toString.append(", "); } RenderingDispatcher.CURRENT.appendPrefix(toString, entry.getKey().getName(), values.entrySet().size()); toString.append(entry.getValue().toString()); } toString.append(')'); return toString.toString(); }
Returns the hash code of the represented annotation.
Returns:The hash code of the represented annotation.
/** * Returns the hash code of the represented annotation. * * @return The hash code of the represented annotation. */
private int hashCodeRepresentation() { int hashCode = 0; for (Map.Entry<Method, AnnotationValue.Loaded<?>> entry : values.entrySet()) { if (!entry.getValue().getState().isDefined()) { continue; } hashCode += (127 * entry.getKey().getName().hashCode()) ^ entry.getValue().hashCode(); } return hashCode; }
Checks if another instance is equal to this instance.
Params:
  • self – The annotation proxy instance.
  • other – The instance to be examined for equality to the represented instance.
Returns:true if the given instance is equal to the represented instance.
/** * Checks if another instance is equal to this instance. * * @param self The annotation proxy instance. * @param other The instance to be examined for equality to the represented instance. * @return {@code true} if the given instance is equal to the represented instance. */
private boolean equalsRepresentation(Object self, Object other) { if (self == other) { return true; } else if (!annotationType.isInstance(other)) { return false; } else if (Proxy.isProxyClass(other.getClass())) { InvocationHandler invocationHandler = Proxy.getInvocationHandler(other); if (invocationHandler instanceof AnnotationInvocationHandler) { return invocationHandler.equals(this); } } try { for (Map.Entry<Method, AnnotationValue.Loaded<?>> entry : values.entrySet()) { try { if (!entry.getValue().represents(entry.getKey().invoke(other, NO_ARGUMENTS))) { return false; } } catch (RuntimeException exception) { return false; // Incomplete annotations are not equal to one another. } } return true; } catch (InvocationTargetException ignored) { return false; } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access annotation property", exception); } } @Override @CachedReturnPlugin.Enhance("hashCode") public int hashCode() { int result = annotationType.hashCode(); result = 31 * result + values.hashCode(); for (Map.Entry<Method, ?> entry : values.entrySet()) { result = 31 * result + entry.getValue().hashCode(); } return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof AnnotationInvocationHandler)) { return false; } AnnotationInvocationHandler that = (AnnotationInvocationHandler) other; if (!annotationType.equals(that.annotationType)) { return false; } for (Map.Entry<Method, AnnotationValue.Loaded<?>> entry : values.entrySet()) { if (!entry.getValue().equals(that.values.get(entry.getKey()))) { return false; } } return true; } }
An adapter implementation of an annotation.
/** * An adapter implementation of an annotation. */
abstract class AbstractBase implements AnnotationDescription {
An array containing all element types that are a legal annotation target when such a target is not specified explicitly.
/** * An array containing all element types that are a legal annotation target when such a target * is not specified explicitly. */
private static final ElementType[] DEFAULT_TARGET = new ElementType[]{ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE};
{@inheritDoc}
/** * {@inheritDoc} */
public RetentionPolicy getRetention() { AnnotationDescription.Loadable<Retention> retention = getAnnotationType().getDeclaredAnnotations().ofType(Retention.class); return retention == null ? RetentionPolicy.CLASS : retention.load().value(); }
{@inheritDoc}
/** * {@inheritDoc} */
public Set<ElementType> getElementTypes() { AnnotationDescription.Loadable<Target> target = getAnnotationType().getDeclaredAnnotations().ofType(Target.class); return new HashSet<ElementType>(Arrays.asList(target == null ? DEFAULT_TARGET : target.load().value())); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isInherited() { return getAnnotationType().getDeclaredAnnotations().isAnnotationPresent(Inherited.class); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isDocumented() { return getAnnotationType().getDeclaredAnnotations().isAnnotationPresent(Documented.class); } @Override @CachedReturnPlugin.Enhance("hashCode") public int hashCode() { int hashCode = 0; for (MethodDescription.InDefinedShape methodDescription : getAnnotationType().getDeclaredMethods()) { hashCode += 31 * getValue(methodDescription).hashCode(); } return hashCode; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof AnnotationDescription)) { return false; } AnnotationDescription annotationDescription = ((AnnotationDescription) other); TypeDescription annotationType = getAnnotationType(); if (!annotationDescription.getAnnotationType().equals(annotationType)) { return false; } for (MethodDescription.InDefinedShape methodDescription : annotationType.getDeclaredMethods()) { if (!getValue(methodDescription).equals(annotationDescription.getValue(methodDescription))) { return false; } } return true; } @Override public String toString() { TypeDescription annotationType = getAnnotationType(); StringBuilder toString = new StringBuilder().append('@').append(annotationType.getName()).append('('); boolean firstMember = true; for (MethodDescription.InDefinedShape methodDescription : annotationType.getDeclaredMethods()) { AnnotationValue<?, ?> value = getValue(methodDescription); if (value.getState() == AnnotationValue.State.UNDEFINED) { continue; } else if (firstMember) { firstMember = false; } else { toString.append(", "); } RenderingDispatcher.CURRENT.appendPrefix(toString, methodDescription.getName(), annotationType.getDeclaredMethods().size()); toString.append(value); } return toString.append(')').toString(); } }
A description of an already loaded annotation.
Type parameters:
  • <S> – The type of the annotation.
/** * A description of an already loaded annotation. * * @param <S> The type of the annotation. */
class ForLoadedAnnotation<S extends Annotation> extends AbstractBase implements Loadable<S> {
The represented annotation value.
/** * The represented annotation value. */
private final S annotation;
The annotation's loaded type which might be loaded by a different class loader than the value's annotation type but must be structurally equal to it.
/** * The annotation's loaded type which might be loaded by a different class loader than the value's * annotation type but must be structurally equal to it. */
private final Class<S> annotationType;
Creates a new annotation description for a loaded annotation.
Params:
  • annotation – The annotation to represent.
/** * Creates a new annotation description for a loaded annotation. * * @param annotation The annotation to represent. */
@SuppressWarnings("unchecked") protected ForLoadedAnnotation(S annotation) { this(annotation, (Class<S>) annotation.annotationType()); }
Creates a new annotation description for a loaded annotation.
Params:
  • annotation – The annotation to represent.
  • annotationType – The annotation's loaded type which might be loaded by a different class loader than the value's annotation type but must be structurally equal to it.
/** * Creates a new annotation description for a loaded annotation. * * @param annotation The annotation to represent. * @param annotationType The annotation's loaded type which might be loaded by a different class loader than the value's * annotation type but must be structurally equal to it. */
private ForLoadedAnnotation(S annotation, Class<S> annotationType) { this.annotation = annotation; this.annotationType = annotationType; }
Creates a description of the given annotation.
Params:
  • annotation – The annotation to be described.
Type parameters:
  • <U> – The type of the annotation.
Returns:A description of the given annotation.
/** * Creates a description of the given annotation. * * @param annotation The annotation to be described. * @param <U> The type of the annotation. * @return A description of the given annotation. */
public static <U extends Annotation> Loadable<U> of(U annotation) { return new ForLoadedAnnotation<U>(annotation); }
{@inheritDoc}
/** * {@inheritDoc} */
public S load() { return annotationType == annotation.annotationType() ? annotation : AnnotationInvocationHandler.of(annotationType.getClassLoader(), annotationType, asValue(annotation)); }
Extracts the annotation values of an annotation into a property map.
Params:
  • annotation – The annotation to convert.
Returns:A mapping of property names to their annotation value.
/** * Extracts the annotation values of an annotation into a property map. * * @param annotation The annotation to convert. * @return A mapping of property names to their annotation value. */
@SuppressWarnings("unchecked") private static Map<String, AnnotationValue<?, ?>> asValue(Annotation annotation) { Map<String, AnnotationValue<?, ?>> annotationValues = new HashMap<String, AnnotationValue<?, ?>>(); for (Method property : annotation.annotationType().getDeclaredMethods()) { try { annotationValues.put(property.getName(), asValue(property.invoke(annotation), property.getReturnType())); } catch (InvocationTargetException exception) { Throwable cause = exception.getCause(); if (cause instanceof TypeNotPresentException) { annotationValues.put(property.getName(), new AnnotationValue.ForMissingType<Void, Void>(((TypeNotPresentException) cause).typeName())); } else if (cause instanceof EnumConstantNotPresentException) { annotationValues.put(property.getName(), new AnnotationValue.ForEnumerationDescription.WithUnknownConstant( new TypeDescription.ForLoadedType(((EnumConstantNotPresentException) cause).enumType()), ((EnumConstantNotPresentException) cause).constantName())); } else if (cause instanceof AnnotationTypeMismatchException) { annotationValues.put(property.getName(), new AnnotationValue.ForMismatchedType<Void, Void>( new MethodDescription.ForLoadedMethod(((AnnotationTypeMismatchException) cause).element()), ((AnnotationTypeMismatchException) cause).foundType())); } else if (!(cause instanceof IncompleteAnnotationException)) { throw new IllegalStateException("Cannot read " + property, exception.getCause()); } } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access " + property, exception); } } return annotationValues; }
Transforms an annotation property to an annotation value.
Params:
  • type – The annotation's type.
  • value – The annotations value.
Returns:An annotation value representation.
/** * Transforms an annotation property to an annotation value. * * @param type The annotation's type. * @param value The annotations value. * @return An annotation value representation. */
@SuppressWarnings("unchecked") public static AnnotationValue<?, ?> asValue(Object value, Class<?> type) { // Because enums can implement annotation interfaces, the enum property needs to be checked first. if (Enum.class.isAssignableFrom(type)) { return AnnotationValue.ForEnumerationDescription.<Enum>of(new EnumerationDescription.ForLoadedEnumeration((Enum) value)); } else if (Enum[].class.isAssignableFrom(type)) { Enum<?>[] element = (Enum<?>[]) value; EnumerationDescription[] enumerationDescription = new EnumerationDescription[element.length]; int index = 0; for (Enum<?> anElement : element) { enumerationDescription[index++] = new EnumerationDescription.ForLoadedEnumeration(anElement); } return AnnotationValue.ForDescriptionArray.<Enum>of(TypeDescription.ForLoadedType.of(type.getComponentType()), enumerationDescription); } else if (Annotation.class.isAssignableFrom(type)) { return AnnotationValue.ForAnnotationDescription.<Annotation>of(TypeDescription.ForLoadedType.of(type), asValue((Annotation) value)); } else if (Annotation[].class.isAssignableFrom(type)) { Annotation[] element = (Annotation[]) value; AnnotationDescription[] annotationDescription = new AnnotationDescription[element.length]; int index = 0; for (Annotation anElement : element) { annotationDescription[index++] = new AnnotationDescription.Latent(TypeDescription.ForLoadedType.of(type.getComponentType()), asValue(anElement)); } return AnnotationValue.ForDescriptionArray.of(TypeDescription.ForLoadedType.of(type.getComponentType()), annotationDescription); } else if (Class.class.isAssignableFrom(type)) { return AnnotationValue.ForTypeDescription.<Class>of(TypeDescription.ForLoadedType.of((Class<?>) value)); } else if (Class[].class.isAssignableFrom(type)) { Class<?>[] element = (Class<?>[]) value; TypeDescription[] typeDescription = new TypeDescription[element.length]; int index = 0; for (Class<?> anElement : element) { typeDescription[index++] = TypeDescription.ForLoadedType.of(anElement); } return AnnotationValue.ForDescriptionArray.of(typeDescription); } else { return AnnotationValue.ForConstant.of(value); } }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("deprecation") @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should always be wrapped for clarity") public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) { if (!property.getDeclaringType().represents(annotation.annotationType())) { throw new IllegalArgumentException(property + " does not represent " + annotation.annotationType()); } try { boolean accessible = property.getDeclaringType().isPublic(); // method is required to be public Method method = property instanceof MethodDescription.ForLoadedMethod ? ((MethodDescription.ForLoadedMethod) property).getLoadedMethod() : null; if (method == null || method.getDeclaringClass() != annotation.annotationType() || (!accessible && !method.isAccessible())) { method = annotation.annotationType().getMethod(property.getName()); if (!accessible) { AccessController.doPrivileged(new SetAccessibleAction<Method>(method)); } } return asValue(method.invoke(annotation), method.getReturnType()).filter(property); } catch (InvocationTargetException exception) { Throwable cause = exception.getCause(); if (cause instanceof TypeNotPresentException) { return new AnnotationValue.ForMissingType<Void, Void>(((TypeNotPresentException) cause).typeName()); } else if (cause instanceof EnumConstantNotPresentException) { return new AnnotationValue.ForEnumerationDescription.WithUnknownConstant( new TypeDescription.ForLoadedType(((EnumConstantNotPresentException) cause).enumType()), ((EnumConstantNotPresentException) cause).constantName()); } else if (cause instanceof AnnotationTypeMismatchException) { return new AnnotationValue.ForMismatchedType<Void, Void>( new MethodDescription.ForLoadedMethod(((AnnotationTypeMismatchException) cause).element()), ((AnnotationTypeMismatchException) cause).foundType()); } else if (cause instanceof IncompleteAnnotationException) { return new AnnotationValue.ForMissingValue<Void, Void>( new TypeDescription.ForLoadedType(((IncompleteAnnotationException) cause).annotationType()), ((IncompleteAnnotationException) cause).elementName()); } else { throw new IllegalStateException("Error reading annotation property " + property, cause); } } catch (Exception exception) { throw new IllegalStateException("Cannot access annotation property " + property, exception); } }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressWarnings("unchecked") public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) { if (!annotation.annotationType().getName().equals(annotationType.getName())) { throw new IllegalArgumentException(annotationType + " does not represent " + annotation.annotationType()); } return annotationType == annotation.annotationType() ? (Loadable<T>) this : new ForLoadedAnnotation<T>((T) annotation, annotationType); }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getAnnotationType() { return TypeDescription.ForLoadedType.of(annotation.annotationType()); } }
A latent description of an annotation value that is defined explicitly.
/** * A latent description of an annotation value that is defined explicitly. */
class Latent extends AbstractBase {
The type of the annotation.
/** * The type of the annotation. */
private final TypeDescription annotationType;
The values of the annotation mapped by their property name.
/** * The values of the annotation mapped by their property name. */
private final Map<String, ? extends AnnotationValue<?, ?>> annotationValues;
Creates a new latent annotation description.
Params:
  • annotationType – The type of the annotation.
  • annotationValues – The values of the annotation mapped by their property name.
/** * Creates a new latent annotation description. * * @param annotationType The type of the annotation. * @param annotationValues The values of the annotation mapped by their property name. */
protected Latent(TypeDescription annotationType, Map<String, ? extends AnnotationValue<?, ?>> annotationValues) { this.annotationType = annotationType; this.annotationValues = annotationValues; }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) { if (!property.getDeclaringType().equals(annotationType)) { throw new IllegalArgumentException("Not a property of " + annotationType + ": " + property); } AnnotationValue<?, ?> value = annotationValues.get(property.getName()); if (value != null) { return value.filter(property); } AnnotationValue<?, ?> defaultValue = property.getDefaultValue(); return defaultValue == null ? new AnnotationValue.ForMissingValue<Void, Void>(annotationType, property.getName()) : defaultValue; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getAnnotationType() { return annotationType; }
{@inheritDoc}
/** * {@inheritDoc} */
public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) { if (!this.annotationType.represents(annotationType)) { throw new IllegalArgumentException(annotationType + " does not represent " + this.annotationType); } return new Loadable<T>(annotationType); }
A loadable annotation description of a latent annotation description.
Type parameters:
  • <S> – The annotation type.
/** * A loadable annotation description of a latent annotation description. * * @param <S> The annotation type. */
protected class Loadable<S extends Annotation> extends AbstractBase implements AnnotationDescription.Loadable<S> {
The annotation type.
/** * The annotation type. */
private final Class<S> annotationType;
Creates a loadable version of a latent annotation description.
Params:
  • annotationType – The annotation type.
/** * Creates a loadable version of a latent annotation description. * * @param annotationType The annotation type. */
protected Loadable(Class<S> annotationType) { this.annotationType = annotationType; }
{@inheritDoc}
/** * {@inheritDoc} */
public S load() { return AnnotationDescription.AnnotationInvocationHandler.of(annotationType.getClassLoader(), annotationType, annotationValues); }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) { return Latent.this.getValue(property); }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getAnnotationType() { return TypeDescription.ForLoadedType.of(annotationType); }
{@inheritDoc}
/** * {@inheritDoc} */
public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) { return Latent.this.prepare(annotationType); } } }
A builder for pragmatically creating AnnotationDescription.
/** * A builder for pragmatically creating {@link net.bytebuddy.description.annotation.AnnotationDescription}. */
@HashCodeAndEqualsPlugin.Enhance class Builder {
The annotation type.
/** * The annotation type. */
private final TypeDescription annotationType;
A mapping of annotation properties to their annotation values.
/** * A mapping of annotation properties to their annotation values. */
private final Map<String, AnnotationValue<?, ?>> annotationValues;
Creates a builder for an annotation description.
Params:
  • annotationType – The annotation type.
  • annotationValues – A mapping of annotation properties to their annotation values.
/** * Creates a builder for an annotation description. * * @param annotationType The annotation type. * @param annotationValues A mapping of annotation properties to their annotation values. */
protected Builder(TypeDescription annotationType, Map<String, AnnotationValue<?, ?>> annotationValues) { this.annotationType = annotationType; this.annotationValues = annotationValues; }
Creates a builder for creating an annotation of the given type.
Params:
  • annotationType – The annotation type.
Returns:A builder for creating an annotation of the given type.
/** * Creates a builder for creating an annotation of the given type. * * @param annotationType The annotation type. * @return A builder for creating an annotation of the given type. */
public static Builder ofType(Class<? extends Annotation> annotationType) { return ofType(TypeDescription.ForLoadedType.of(annotationType)); }
Creates a builder for creating an annotation of the given type.
Params:
  • annotationType – A description of the annotation type.
Returns:A builder for creating an annotation of the given type.
/** * Creates a builder for creating an annotation of the given type. * * @param annotationType A description of the annotation type. * @return A builder for creating an annotation of the given type. */
public static Builder ofType(TypeDescription annotationType) { if (!annotationType.isAnnotation()) { throw new IllegalArgumentException("Not an annotation type: " + annotationType); } return new Builder(annotationType, Collections.<String, AnnotationValue<?, ?>>emptyMap()); }
Returns a builder with the additional, given property.
Params:
  • property – The name of the property to define.
  • value – An explicit description of the annotation value.
Returns:A builder with the additional, given property.
/** * Returns a builder with the additional, given property. * * @param property The name of the property to define. * @param value An explicit description of the annotation value. * @return A builder with the additional, given property. */
public Builder define(String property, AnnotationValue<?, ?> value) { MethodList<MethodDescription.InDefinedShape> methodDescriptions = annotationType.getDeclaredMethods().filter(named(property)); if (methodDescriptions.isEmpty()) { throw new IllegalArgumentException(annotationType + " does not define a property named " + property); } Map<String, AnnotationValue<?, ?>> annotationValues = new HashMap<String, AnnotationValue<?, ?>>(this.annotationValues); if (annotationValues.put(methodDescriptions.getOnly().getName(), value) != null) { throw new IllegalArgumentException("Property already defined: " + property); } return new Builder(annotationType, annotationValues); }
Returns a builder with the additional enumeration property.
Params:
  • property – The name of the property to define.
  • value – The enumeration value to define.
Returns:A builder with the additional enumeration property.
/** * Returns a builder with the additional enumeration property. * * @param property The name of the property to define. * @param value The enumeration value to define. * @return A builder with the additional enumeration property. */
public Builder define(String property, Enum<?> value) { return define(property, new EnumerationDescription.ForLoadedEnumeration(value)); }
Returns a builder with the additional enumeration property.
Params:
  • property – The name of the property to define.
  • enumerationType – The type of the enumeration.
  • value – The enumeration value to define.
Returns:A builder with the additional enumeration property.
/** * Returns a builder with the additional enumeration property. * * @param property The name of the property to define. * @param enumerationType The type of the enumeration. * @param value The enumeration value to define. * @return A builder with the additional enumeration property. */
public Builder define(String property, TypeDescription enumerationType, String value) { return define(property, new EnumerationDescription.Latent(enumerationType, value)); }
Returns a builder with the additional enumeration property.
Params:
  • property – The name of the property to define.
  • value – A description of the enumeration value to define.
Returns:A builder with the additional enumeration property.
/** * Returns a builder with the additional enumeration property. * * @param property The name of the property to define. * @param value A description of the enumeration value to define. * @return A builder with the additional enumeration property. */
@SuppressWarnings("unchecked") public Builder define(String property, EnumerationDescription value) { return define(property, AnnotationValue.ForEnumerationDescription.<Enum>of(value)); }
Returns a builder with the additional annotation property.
Params:
  • property – The name of the property to define.
  • annotation – The annotation value to define.
Returns:A builder with the additional annotation property.
/** * Returns a builder with the additional annotation property. * * @param property The name of the property to define. * @param annotation The annotation value to define. * @return A builder with the additional annotation property. */
public Builder define(String property, Annotation annotation) { return define(property, new ForLoadedAnnotation<Annotation>(annotation)); }
Returns a builder with the additional annotation property.
Params:
  • property – The name of the property to define.
  • annotationDescription – A description of the annotation value to define.
Returns:A builder with the additional annotation property.
/** * Returns a builder with the additional annotation property. * * @param property The name of the property to define. * @param annotationDescription A description of the annotation value to define. * @return A builder with the additional annotation property. */
public Builder define(String property, AnnotationDescription annotationDescription) { return define(property, new AnnotationValue.ForAnnotationDescription<Annotation>(annotationDescription)); }
Returns a builder with the additional class property.
Params:
  • property – The name of the property to define.
  • type – The class value to define.
Returns:A builder with the additional class property.
/** * Returns a builder with the additional class property. * * @param property The name of the property to define. * @param type The class value to define. * @return A builder with the additional class property. */
public Builder define(String property, Class<?> type) { return define(property, TypeDescription.ForLoadedType.of(type)); }
Returns a builder with the additional class property.
Params:
  • property – The name of the property to define.
  • typeDescription – A description of the type to define as a property value.
Returns:A builder with the additional class property.
/** * Returns a builder with the additional class property. * * @param property The name of the property to define. * @param typeDescription A description of the type to define as a property value. * @return A builder with the additional class property. */
@SuppressWarnings("unchecked") public Builder define(String property, TypeDescription typeDescription) { return define(property, AnnotationValue.ForTypeDescription.<Class>of(typeDescription)); }
Returns a builder with the additional enumeration array property.
Params:
  • property – The name of the property to define.
  • enumerationType – The type of the enumeration, i.e. the component type of the enumeration array.
  • value – The enumeration values to be contained by the array.
Type parameters:
  • <T> – The enumeration type.
Returns:A builder with the additional class property.
/** * Returns a builder with the additional enumeration array property. * * @param property The name of the property to define. * @param enumerationType The type of the enumeration, i.e. the component type of the enumeration array. * @param value The enumeration values to be contained by the array. * @param <T> The enumeration type. * @return A builder with the additional class property. */
@SuppressWarnings("unchecked") public <T extends Enum<?>> Builder defineEnumerationArray(String property, Class<T> enumerationType, T... value) { EnumerationDescription[] enumerationDescription = new EnumerationDescription[value.length]; int index = 0; for (T aValue : value) { enumerationDescription[index++] = new EnumerationDescription.ForLoadedEnumeration(aValue); } return defineEnumerationArray(property, TypeDescription.ForLoadedType.of(enumerationType), enumerationDescription); }
Returns a builder with the additional enumeration array property.
Params:
  • property – The name of the property to define.
  • enumerationType – The type of the enumerations, i.e. is the component type of the enumeration array.
  • value – The enumeration values to be contained by the array.
Returns:A builder with the additional enumeration property.
/** * Returns a builder with the additional enumeration array property. * * @param property The name of the property to define. * @param enumerationType The type of the enumerations, i.e. is the component type of the enumeration array. * @param value The enumeration values to be contained by the array. * @return A builder with the additional enumeration property. */
public Builder defineEnumerationArray(String property, TypeDescription enumerationType, String... value) { if (!enumerationType.isEnum()) { throw new IllegalArgumentException("Not an enumeration type: " + enumerationType); } EnumerationDescription[] enumerationDescription = new EnumerationDescription[value.length]; for (int i = 0; i < value.length; i++) { enumerationDescription[i] = new EnumerationDescription.Latent(enumerationType, value[i]); } return defineEnumerationArray(property, enumerationType, enumerationDescription); }
Returns a builder with the additional enumeration array property.
Params:
  • property – The name of the property to define.
  • enumerationType – The type of the enumerations, i.e. the component type of the enumeration array.
  • value – Descriptions of the enumerations to be contained by the array.
Returns:A builder with the additional enumeration property.
/** * Returns a builder with the additional enumeration array property. * * @param property The name of the property to define. * @param enumerationType The type of the enumerations, i.e. the component type of the enumeration array. * @param value Descriptions of the enumerations to be contained by the array. * @return A builder with the additional enumeration property. */
@SuppressWarnings("unchecked") public Builder defineEnumerationArray(String property, TypeDescription enumerationType, EnumerationDescription... value) { return define(property, AnnotationValue.ForDescriptionArray.<Enum>of(enumerationType, value)); }
Returns a builder with the additional annotation array property.
Params:
  • property – The name of the property to define.
  • annotationType – The type of the annotations, i.e. the component type of the enumeration array.
  • annotation – The annotation values to be contained by the array.
Type parameters:
  • <T> – The annotation type.
Returns:A builder with the additional annotation property.
/** * Returns a builder with the additional annotation array property. * * @param property The name of the property to define. * @param annotationType The type of the annotations, i.e. the component type of the enumeration array. * @param annotation The annotation values to be contained by the array. * @param <T> The annotation type. * @return A builder with the additional annotation property. */
@SuppressWarnings("unchecked") public <T extends Annotation> Builder defineAnnotationArray(String property, Class<T> annotationType, T... annotation) { return defineAnnotationArray(property, TypeDescription.ForLoadedType.of(annotationType), new AnnotationList.ForLoadedAnnotations(annotation).toArray(new AnnotationDescription[0])); }
Returns a builder with the additional annotation array property.
Params:
  • property – The name of the property to define.
  • annotationType – The type of the annotations, i.e. the component type of the enumeration array.
  • annotationDescription – Descriptions of the annotation values to be contained by the array.
Returns:A builder with the additional annotation property.
/** * Returns a builder with the additional annotation array property. * * @param property The name of the property to define. * @param annotationType The type of the annotations, i.e. the component type of the enumeration array. * @param annotationDescription Descriptions of the annotation values to be contained by the array. * @return A builder with the additional annotation property. */
public Builder defineAnnotationArray(String property, TypeDescription annotationType, AnnotationDescription... annotationDescription) { return define(property, AnnotationValue.ForDescriptionArray.of(annotationType, annotationDescription)); }
Returns a builder with the additional type array property.
Params:
  • property – The name of the property to define.
  • type – The types that should be contained by the array.
Returns:A builder with the additional type array property.
/** * Returns a builder with the additional type array property. * * @param property The name of the property to define. * @param type The types that should be contained by the array. * @return A builder with the additional type array property. */
public Builder defineTypeArray(String property, Class<?>... type) { return defineTypeArray(property, new TypeList.ForLoadedTypes(type).toArray(new TypeDescription[0])); }
Returns a builder with the additional type array property.
Params:
  • property – The name of the property to define.
  • typeDescription – Descriptions of the types that should be contained by the array.
Returns:A builder with the additional type array property.
/** * Returns a builder with the additional type array property. * * @param property The name of the property to define. * @param typeDescription Descriptions of the types that should be contained by the array. * @return A builder with the additional type array property. */
public Builder defineTypeArray(String property, TypeDescription... typeDescription) { return define(property, AnnotationValue.ForDescriptionArray.of(typeDescription)); }
Returns a builder with the additional boolean property.
Params:
  • property – The name of the property to define.
  • value – The boolean value to define for the property.
Returns:A builder with the additional boolean property.
/** * Returns a builder with the additional {@code boolean} property. * * @param property The name of the property to define. * @param value The {@code boolean} value to define for the property. * @return A builder with the additional {@code boolean} property. */
public Builder define(String property, boolean value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional byte property.
Params:
  • property – The name of the property to define.
  • value – The byte value to define for the property.
Returns:A builder with the additional byte property.
/** * Returns a builder with the additional {@code byte} property. * * @param property The name of the property to define. * @param value The {@code byte} value to define for the property. * @return A builder with the additional {@code byte} property. */
public Builder define(String property, byte value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional char property.
Params:
  • property – The name of the property to define.
  • value – The char value to define for the property.
Returns:A builder with the additional char property.
/** * Returns a builder with the additional {@code char} property. * * @param property The name of the property to define. * @param value The {@code char} value to define for the property. * @return A builder with the additional {@code char} property. */
public Builder define(String property, char value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional short property.
Params:
  • property – The name of the property to define.
  • value – The short value to define for the property.
Returns:A builder with the additional short property.
/** * Returns a builder with the additional {@code short} property. * * @param property The name of the property to define. * @param value The {@code short} value to define for the property. * @return A builder with the additional {@code short} property. */
public Builder define(String property, short value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional int property.
Params:
  • property – The name of the property to define.
  • value – The int value to define for the property.
Returns:A builder with the additional int property.
/** * Returns a builder with the additional {@code int} property. * * @param property The name of the property to define. * @param value The {@code int} value to define for the property. * @return A builder with the additional {@code int} property. */
public Builder define(String property, int value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional long property.
Params:
  • property – The name of the property to define.
  • value – The long value to define for the property.
Returns:A builder with the additional long property.
/** * Returns a builder with the additional {@code long} property. * * @param property The name of the property to define. * @param value The {@code long} value to define for the property. * @return A builder with the additional {@code long} property. */
public Builder define(String property, long value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional float property.
Params:
  • property – The name of the property to define.
  • value – The float value to define for the property.
Returns:A builder with the additional float property.
/** * Returns a builder with the additional {@code float} property. * * @param property The name of the property to define. * @param value The {@code float} value to define for the property. * @return A builder with the additional {@code float} property. */
public Builder define(String property, float value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional double property.
Params:
  • property – The name of the property to define.
  • value – The double value to define for the property.
Returns:A builder with the additional double property.
/** * Returns a builder with the additional {@code double} property. * * @param property The name of the property to define. * @param value The {@code double} value to define for the property. * @return A builder with the additional {@code double} property. */
public Builder define(String property, double value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional String property.
Params:
  • property – The name of the property to define.
  • value – The String value to define for the property.
Returns:A builder with the additional String property.
/** * Returns a builder with the additional {@link java.lang.String} property. * * @param property The name of the property to define. * @param value The {@link java.lang.String} value to define for the property. * @return A builder with the additional {@link java.lang.String} property. */
public Builder define(String property, String value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional boolean array property.
Params:
  • property – The name of the property to define.
  • value – The boolean values to define for the property.
Returns:A builder with the additional boolean array property.
/** * Returns a builder with the additional {@code boolean} array property. * * @param property The name of the property to define. * @param value The {@code boolean} values to define for the property. * @return A builder with the additional {@code boolean} array property. */
public Builder defineArray(String property, boolean... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional byte array property.
Params:
  • property – The name of the property to define.
  • value – The byte values to define for the property.
Returns:A builder with the additional byte array property.
/** * Returns a builder with the additional {@code byte} array property. * * @param property The name of the property to define. * @param value The {@code byte} values to define for the property. * @return A builder with the additional {@code byte} array property. */
public Builder defineArray(String property, byte... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional char array property.
Params:
  • property – The name of the property to define.
  • value – The char values to define for the property.
Returns:A builder with the additional char array property.
/** * Returns a builder with the additional {@code char} array property. * * @param property The name of the property to define. * @param value The {@code char} values to define for the property. * @return A builder with the additional {@code char} array property. */
public Builder defineArray(String property, char... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional short array property.
Params:
  • property – The name of the property to define.
  • value – The short values to define for the property.
Returns:A builder with the additional short array property.
/** * Returns a builder with the additional {@code short} array property. * * @param property The name of the property to define. * @param value The {@code short} values to define for the property. * @return A builder with the additional {@code short} array property. */
public Builder defineArray(String property, short... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional int array property.
Params:
  • property – The name of the property to define.
  • value – The int values to define for the property.
Returns:A builder with the additional int array property.
/** * Returns a builder with the additional {@code int} array property. * * @param property The name of the property to define. * @param value The {@code int} values to define for the property. * @return A builder with the additional {@code int} array property. */
public Builder defineArray(String property, int... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional long array property.
Params:
  • property – The name of the property to define.
  • value – The long values to define for the property.
Returns:A builder with the additional long array property.
/** * Returns a builder with the additional {@code long} array property. * * @param property The name of the property to define. * @param value The {@code long} values to define for the property. * @return A builder with the additional {@code long} array property. */
public Builder defineArray(String property, long... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional float array property.
Params:
  • property – The name of the property to define.
  • value – The float values to define for the property.
Returns:A builder with the additional float array property.
/** * Returns a builder with the additional {@code float} array property. * * @param property The name of the property to define. * @param value The {@code float} values to define for the property. * @return A builder with the additional {@code float} array property. */
public Builder defineArray(String property, float... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional double array property.
Params:
  • property – The name of the property to define.
  • value – The double values to define for the property.
Returns:A builder with the additional double array property.
/** * Returns a builder with the additional {@code double} array property. * * @param property The name of the property to define. * @param value The {@code double} values to define for the property. * @return A builder with the additional {@code double} array property. */
public Builder defineArray(String property, double... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Returns a builder with the additional String array property.
Params:
  • property – The name of the property to define.
  • value – The String array value to define for the property.
Returns:A builder with the additional String array property.
/** * Returns a builder with the additional {@link java.lang.String} array property. * * @param property The name of the property to define. * @param value The {@link java.lang.String} array value to define for the property. * @return A builder with the additional {@link java.lang.String} array property. */
public Builder defineArray(String property, String... value) { return define(property, AnnotationValue.ForConstant.of(value)); }
Creates an annotation description for the values that were defined for this builder. It is validated that all properties are defined if no default value is set for an annotation property.
Returns:An appropriate annotation description.
/** * Creates an annotation description for the values that were defined for this builder. It is validated that all * properties are defined if no default value is set for an annotation property. * * @return An appropriate annotation description. */
public AnnotationDescription build() { for (MethodDescription.InDefinedShape methodDescription : annotationType.getDeclaredMethods()) { AnnotationValue<?, ?> annotationValue = annotationValues.get(methodDescription.getName()); if (annotationValue == null && methodDescription.getDefaultValue() == null) { throw new IllegalStateException("No value or default value defined for " + methodDescription.getName()); } else if (annotationValue != null && annotationValue.filter(methodDescription).getState() != AnnotationValue.State.RESOLVED) { throw new IllegalStateException("Illegal annotation value for " + methodDescription + ": " + annotationValue); } } return new Latent(annotationType, annotationValues); }
Creates an annotation description for the values that were defined for this builder.
Params:
  • validated – true if the annotation description should be validated for having included all values.
Returns:An appropriate annotation description.
/** * Creates an annotation description for the values that were defined for this builder. * * @param validated {@code true} if the annotation description should be validated for having included all values. * @return An appropriate annotation description. */
public AnnotationDescription build(boolean validated) { return validated ? build() : new Latent(annotationType, annotationValues); } } }