/*
* Copyright 2014 - 2019 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 net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.enumeration.EnumerationDescription;
import net.bytebuddy.description.type.TypeDescription;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.*;
Representation of an unloaded annotation value where all values represent either:
- Primitive values (as their wrappers),
String
s or arrays of primitive types or strings.
- A
TypeDescription
or an array of such a descriptions.
- An
EnumerationDescription
or an array of such a description.
- An
AnnotationDescription
or an array of such a description.
The represented values are not necessarily resolvable, i.e. can contain non-available types, unknown enumeration
constants or inconsistent annotations.
Type parameters:
/**
* Representation of an unloaded annotation value where all values represent either:
* <ul>
* <li>Primitive values (as their wrappers), {@link String}s or arrays of primitive types or strings.</li>
* <li>A {@link TypeDescription} or an array of such a descriptions.</li>
* <li>An {@link EnumerationDescription} or an array of such a description.</li>
* <li>An {@link AnnotationDescription} or an array of such a description.</li>
* </ul>
* The represented values are not necessarily resolvable, i.e. can contain non-available types, unknown enumeration
* constants or inconsistent annotations.
*
* @param <T> The represented value's unloaded type.
* @param <S> The represented value's loaded type.
*/
public interface AnnotationValue<T, S> {
An undefined annotation value.
/**
* An undefined annotation value.
*/
AnnotationValue<?, ?> UNDEFINED = null;
Resolves the unloaded value of this annotation.
Returns: The unloaded value of this annotation.
/**
* Resolves the unloaded value of this annotation.
*
* @return The unloaded value of this annotation.
*/
T resolve();
Resolves the unloaded value of this annotation.
Params: - type – The annotation value's unloaded type.
Type parameters: - <W> – The annotation value's unloaded type.
Returns: The unloaded value of this annotation.
/**
* Resolves the unloaded value of this annotation.
*
* @param type The annotation value's unloaded type.
* @param <W> The annotation value's unloaded type.
* @return The unloaded value of this annotation.
*/
<W> W resolve(Class<? extends W> type);
Returns the loaded value of this annotation.
Params: - classLoader – The class loader for loading this value.
Throws: - ClassNotFoundException – If a type that represents a loaded value cannot be found.
Returns: The loaded value of this annotation.
/**
* Returns the loaded value of this annotation.
*
* @param classLoader The class loader for loading this value.
* @return The loaded value of this annotation.
* @throws ClassNotFoundException If a type that represents a loaded value cannot be found.
*/
Loaded<S> load(ClassLoader classLoader) throws ClassNotFoundException;
Returns the loaded value of this annotation without throwing a checked exception.
Params: - classLoader – The class loader for loading this value.
Returns: The loaded value of this annotation.
/**
* Returns the loaded value of this annotation without throwing a checked exception.
*
* @param classLoader The class loader for loading this value.
* @return The loaded value of this annotation.
*/
Loaded<S> loadSilent(ClassLoader classLoader);
A rendering dispatcher is responsible for resolving annotation values to String
representations. /**
* A rendering dispatcher is responsible for resolving annotation values to {@link String} representations.
*/
enum RenderingDispatcher {
A rendering dispatcher for any VM previous to Java 9.
/**
* A rendering dispatcher for any VM previous to Java 9.
*/
LEGACY_VM('[', ']') {
@Override
public String toSourceString(char value) {
return Character.toString(value);
}
@Override
public String toSourceString(long value) {
return Long.toString(value);
}
@Override
public String toSourceString(float value) {
return Float.toString(value);
}
@Override
public String toSourceString(double value) {
return Double.toString(value);
}
@Override
public String toSourceString(String value) {
return value;
}
@Override
public String toSourceString(TypeDescription value) {
return value.toString();
}
},
A rendering dispatcher for Java 9 onward.
/**
* A rendering dispatcher for Java 9 onward.
*/
JAVA_9_CAPABLE_VM('{', '}') {
@Override
public String toSourceString(char value) {
StringBuilder stringBuilder = new StringBuilder().append('\'');
if (value == '\'') {
stringBuilder.append("\\\'");
} else {
stringBuilder.append(value);
}
return stringBuilder.append('\'').toString();
}
@Override
public String toSourceString(long value) {
return Math.abs(value) <= Integer.MAX_VALUE
? String.valueOf(value)
: value + "L";
}
@Override
public String toSourceString(float value) {
return Math.abs(value) <= Float.MAX_VALUE // Float.isFinite(value)
? Float.toString(value) + "f"
: (Float.isInfinite(value) ? (value < 0.0f ? "-1.0f/0.0f" : "1.0f/0.0f") : "0.0f/0.0f");
}
@Override
public String toSourceString(double value) {
return Math.abs(value) <= Double.MAX_VALUE // Double.isFinite(value)
? Double.toString(value)
: (Double.isInfinite(value) ? (value < 0.0d ? "-1.0/0.0" : "1.0/0.0") : "0.0/0.0");
}
@Override
public String toSourceString(String value) {
return "\"" + (value.indexOf('"') == -1
? value
: value.replace("\"", "\\\"")) + "\"";
}
@Override
public String toSourceString(TypeDescription value) {
return value.getActualName() + ".class";
}
};
The rendering dispatcher for the current VM.
/**
* The rendering dispatcher for the current VM.
*/
public static final RenderingDispatcher CURRENT = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6).isAtLeast(ClassFileVersion.JAVA_V9)
? JAVA_9_CAPABLE_VM
: LEGACY_VM;
The opening brace of an array String
representation. /**
* The opening brace of an array {@link String} representation.
*/
private final char openingBrace;
The closing brace of an array String
representation. /**
* The closing brace of an array {@link String} representation.
*/
private final char closingBrace;
Creates a new rendering dispatcher.
Params:
/**
* Creates a new rendering dispatcher.
*
* @param openingBrace The opening brace of an array {@link String} representation.
* @param closingBrace The closing brace of an array {@link String} representation.
*/
RenderingDispatcher(char openingBrace, char closingBrace) {
this.openingBrace = openingBrace;
this.closingBrace = closingBrace;
}
Represents the supplied boolean
value as a String
. Params: - value – The
boolean
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code boolean} value as a {@link String}.
*
* @param value The {@code boolean} value to render.
* @return An appropriate {@link String} representation.
*/
public String toSourceString(boolean value) {
return Boolean.toString(value);
}
Represents the supplied boolean
value as a String
. Params: - value – The
boolean
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code boolean} value as a {@link String}.
*
* @param value The {@code boolean} value to render.
* @return An appropriate {@link String} representation.
*/
public String toSourceString(byte value) {
return Byte.toString(value);
}
Represents the supplied short
value as a String
. Params: - value – The
short
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code short} value as a {@link String}.
*
* @param value The {@code short} value to render.
* @return An appropriate {@link String} representation.
*/
public String toSourceString(short value) {
return Short.toString(value);
}
Represents the supplied char
value as a String
. Params: - value – The
char
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code char} value as a {@link String}.
*
* @param value The {@code char} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(char value);
Represents the supplied int
value as a String
. Params: - value – The
int
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code int} value as a {@link String}.
*
* @param value The {@code int} value to render.
* @return An appropriate {@link String} representation.
*/
public String toSourceString(int value) {
return Integer.toString(value);
}
Represents the supplied long
value as a String
. Params: - value – The
long
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code long} value as a {@link String}.
*
* @param value The {@code long} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(long value);
Represents the supplied float
value as a String
. Params: - value – The
float
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code float} value as a {@link String}.
*
* @param value The {@code float} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(float value);
Represents the supplied double
value as a String
. Params: - value – The
double
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@code double} value as a {@link String}.
*
* @param value The {@code double} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(double value);
Params: - value – The
String
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@link String} value as a {@link String}.
*
* @param value The {@link String} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(String value);
Represents the supplied TypeDescription
value as a String
. Params: - value – The
TypeDescription
value to render.
Returns: An appropriate String
representation.
/**
* Represents the supplied {@link TypeDescription} value as a {@link String}.
*
* @param value The {@link TypeDescription} value to render.
* @return An appropriate {@link String} representation.
*/
public abstract String toSourceString(TypeDescription value);
Represents the supplied list elements as a String
. Params: - values – The elements to render where each element is represented by its
Object.toString()
representation.
Returns: An appropriate String
representation.
/**
* Represents the supplied list elements as a {@link String}.
*
* @param values The elements to render where each element is represented by its {@link Object#toString()} representation.
* @return An appropriate {@link String} representation.
*/
public String toSourceString(List<?> values) {
StringBuilder stringBuilder = new StringBuilder().append(openingBrace);
boolean first = true;
for (Object value : values) {
if (first) {
first = false;
} else {
stringBuilder.append(", ");
}
stringBuilder.append(value);
}
return stringBuilder.append(closingBrace).toString();
}
}
A loaded variant of an AnnotationValue
. While implementations of this value are required to be processed successfully by a ClassLoader
they might still be unresolved. Typical errors on loading an annotation value are:
IncompleteAnnotationException
: An annotation does not define a value even though no default value for a property is provided.
EnumConstantNotPresentException
: An annotation defines an unknown value for a known enumeration.
AnnotationTypeMismatchException
: An annotation property is not of the expected type.
Implementations of this interface must implement methods for Object.hashCode()
and Object.toString()
that resemble those used for the annotation values of an actual Annotation
implementation. Also, instances must implement Object.equals(Object)
to return true
for other instances of this interface that represent the same annotation value. Type parameters: - <U> – The represented value's type.
/**
* A loaded variant of an {@link AnnotationValue}. While
* implementations of this value are required to be processed successfully by a
* {@link java.lang.ClassLoader} they might still be unresolved. Typical errors on loading an annotation
* value are:
* <ul>
* <li>{@link java.lang.annotation.IncompleteAnnotationException}: An annotation does not define a value
* even though no default value for a property is provided.</li>
* <li>{@link java.lang.EnumConstantNotPresentException}: An annotation defines an unknown value for
* a known enumeration.</li>
* <li>{@link java.lang.annotation.AnnotationTypeMismatchException}: An annotation property is not
* of the expected type.</li>
* </ul>
* Implementations of this interface must implement methods for {@link Object#hashCode()} and
* {@link Object#toString()} that resemble those used for the annotation values of an actual
* {@link java.lang.annotation.Annotation} implementation. Also, instances must implement
* {@link java.lang.Object#equals(Object)} to return {@code true} for other instances of
* this interface that represent the same annotation value.
*
* @param <U> The represented value's type.
*/
interface Loaded<U> {
Returns the state of the represented loaded annotation value.
Returns: The state represented by this instance.
/**
* Returns the state of the represented loaded annotation value.
*
* @return The state represented by this instance.
*/
State getState();
Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
exception if this value is either not defined or not resolved.
Returns: The actual annotation value represented by this instance.
/**
* Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
* exception if this value is either not defined or not resolved.
*
* @return The actual annotation value represented by this instance.
*/
U resolve();
Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
exception if this value is either not defined or not resolved.
Params: - type – The value's loaded type.
Type parameters: - <V> – The value's loaded type.
Returns: The actual annotation value represented by this instance.
/**
* Resolves the value to the actual value of an annotation. Calling this method might throw a runtime
* exception if this value is either not defined or not resolved.
*
* @param type The value's loaded type.
* @param <V> The value's loaded type.
* @return The actual annotation value represented by this instance.
*/
<V> V resolve(Class<? extends V> type);
Verifies if this loaded value represents the supplied loaded value.
Params: - value – A loaded annotation value.
Returns: true
if the supplied annotation value is represented by this annotation value.
/**
* Verifies if this loaded value represents the supplied loaded value.
*
* @param value A loaded annotation value.
* @return {@code true} if the supplied annotation value is represented by this annotation value.
*/
boolean represents(Object value);
Represents the state of a Loaded
annotation property. /**
* Represents the state of a {@link Loaded} annotation property.
*/
enum State {
An undefined annotation value describes an annotation property which is missing such that an IncompleteAnnotationException
would be thrown. /**
* An undefined annotation value describes an annotation property which is missing such that
* an {@link java.lang.annotation.IncompleteAnnotationException} would be thrown.
*/
UNDEFINED,
An unresolved annotation value describes an annotation property which does not represent a
valid value but an exceptional state.
/**
* An unresolved annotation value describes an annotation property which does not represent a
* valid value but an exceptional state.
*/
UNRESOLVED,
A resolved annotation value describes an annotation property with an actual value.
/**
* A resolved annotation value describes an annotation property with an actual value.
*/
RESOLVED;
Returns true
if the related annotation value is defined, i.e. either represents an actual value or an exceptional state. Returns: true
if the related annotation value is defined.
/**
* Returns {@code true} if the related annotation value is defined, i.e. either represents
* an actual value or an exceptional state.
*
* @return {@code true} if the related annotation value is defined.
*/
public boolean isDefined() {
return this != UNDEFINED;
}
Returns true
if the related annotation value is resolved, i.e. represents an actual value. Returns: true
if the related annotation value is resolved.
/**
* Returns {@code true} if the related annotation value is resolved, i.e. represents an actual
* value.
*
* @return {@code true} if the related annotation value is resolved.
*/
public boolean isResolved() {
return this == RESOLVED;
}
}
An abstract base implementation of a loaded annotation value.
Type parameters: - <W> – The represented loaded type.
/**
* An abstract base implementation of a loaded annotation value.
*
* @param <W> The represented loaded type.
*/
abstract class AbstractBase<W> implements Loaded<W> {
{@inheritDoc}
/**
* {@inheritDoc}
*/
public <X> X resolve(Class<? extends X> type) {
return type.cast(resolve());
}
}
}
An abstract base implementation of an unloaded annotation value.
Type parameters: - <U> – The represented unloaded type.
- <V> – The represented loaded type.
/**
* An abstract base implementation of an unloaded annotation value.
*
* @param <U> The represented unloaded type.
* @param <V> The represented loaded type.
*/
abstract class AbstractBase<U, V> implements AnnotationValue<U, V> {
{@inheritDoc}
/**
* {@inheritDoc}
*/
public <W> W resolve(Class<? extends W> type) {
return type.cast(resolve());
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Loaded<V> loadSilent(ClassLoader classLoader) {
try {
return load(classLoader);
} catch (ClassNotFoundException exception) {
throw new IllegalStateException("Cannot load " + this, exception);
}
}
}
Represents a primitive value, a String
or an array of the latter types. Type parameters: - <U> – The type where primitive values are represented by their boxed type.
/**
* Represents a primitive value, a {@link java.lang.String} or an array of the latter types.
*
* @param <U> The type where primitive values are represented by their boxed type.
*/
class ForConstant<U> extends AbstractBase<U, U> {
The represented value.
/**
* The represented value.
*/
private final U value;
The property delegate for the value's type.
/**
* The property delegate for the value's type.
*/
private final PropertyDelegate propertyDelegate;
Creates a new constant annotation value.
Params: - value – The represented value.
- propertyDelegate – The property delegate for the value's type.
/**
* Creates a new constant annotation value.
*
* @param value The represented value.
* @param propertyDelegate The property delegate for the value's type.
*/
protected ForConstant(U value, PropertyDelegate propertyDelegate) {
this.value = value;
this.propertyDelegate = propertyDelegate;
}
Creates an annotation value for a boolean
value. Params: - value – The
boolean
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code boolean} value.
*
* @param value The {@code boolean} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Boolean, Boolean> of(boolean value) {
return new ForConstant<Boolean>(value, PropertyDelegate.ForNonArrayType.BOOLEAN);
}
Creates an annotation value for a byte
value. Params: - value – The
byte
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code byte} value.
*
* @param value The {@code byte} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Byte, Byte> of(byte value) {
return new ForConstant<Byte>(value, PropertyDelegate.ForNonArrayType.BYTE);
}
Creates an annotation value for a short
value. Params: - value – The
short
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code short} value.
*
* @param value The {@code short} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Short, Short> of(short value) {
return new ForConstant<Short>(value, PropertyDelegate.ForNonArrayType.SHORT);
}
Creates an annotation value for a char
value. Params: - value – The
char
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code char} value.
*
* @param value The {@code char} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Character, Character> of(char value) {
return new ForConstant<Character>(value, PropertyDelegate.ForNonArrayType.CHARACTER);
}
Creates an annotation value for a int
value. Params: - value – The
int
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code int} value.
*
* @param value The {@code int} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Integer, Integer> of(int value) {
return new ForConstant<Integer>(value, PropertyDelegate.ForNonArrayType.INTEGER);
}
Creates an annotation value for a long
value. Params: - value – The
long
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code long} value.
*
* @param value The {@code long} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Long, Long> of(long value) {
return new ForConstant<Long>(value, PropertyDelegate.ForNonArrayType.LONG);
}
Creates an annotation value for a float
value. Params: - value – The
float
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code float} value.
*
* @param value The {@code float} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Float, Float> of(float value) {
return new ForConstant<Float>(value, PropertyDelegate.ForNonArrayType.FLOAT);
}
Creates an annotation value for a double
value. Params: - value – The
double
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code double} value.
*
* @param value The {@code double} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<Double, Double> of(double value) {
return new ForConstant<Double>(value, PropertyDelegate.ForNonArrayType.DOUBLE);
}
Creates an annotation value for a String
value. Params: - value – The
String
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@link String} value.
*
* @param value The {@link String} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<String, String> of(String value) {
return new ForConstant<String>(value, PropertyDelegate.ForNonArrayType.STRING);
}
Creates an annotation value for a boolean[]
value. Params: - value – The
boolean[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code boolean[]} value.
*
* @param value The {@code boolean[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<boolean[], boolean[]> of(boolean... value) {
return new ForConstant<boolean[]>(value, PropertyDelegate.ForArrayType.BOOLEAN);
}
Creates an annotation value for a byte[]
value. Params: - value – The
byte[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code byte[]} value.
*
* @param value The {@code byte[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<byte[], byte[]> of(byte... value) {
return new ForConstant<byte[]>(value, PropertyDelegate.ForArrayType.BYTE);
}
Creates an annotation value for a short[]
value. Params: - value – The
short[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code short[]} value.
*
* @param value The {@code short[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<short[], short[]> of(short... value) {
return new ForConstant<short[]>(value, PropertyDelegate.ForArrayType.SHORT);
}
Creates an annotation value for a char[]
value. Params: - value – The
char[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code char[]} value.
*
* @param value The {@code char[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<char[], char[]> of(char... value) {
return new ForConstant<char[]>(value, PropertyDelegate.ForArrayType.CHARACTER);
}
Creates an annotation value for a int[]
value. Params: - value – The
int[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code int[]} value.
*
* @param value The {@code int[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<int[], int[]> of(int... value) {
return new ForConstant<int[]>(value, PropertyDelegate.ForArrayType.INTEGER);
}
Creates an annotation value for a long[]
value. Params: - value – The
long[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code long[]} value.
*
* @param value The {@code long[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<long[], long[]> of(long... value) {
return new ForConstant<long[]>(value, PropertyDelegate.ForArrayType.LONG);
}
Creates an annotation value for a float[]
value. Params: - value – The
float[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code float[]} value.
*
* @param value The {@code float[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<float[], float[]> of(float... value) {
return new ForConstant<float[]>(value, PropertyDelegate.ForArrayType.FLOAT);
}
Creates an annotation value for a double[]
value. Params: - value – The
double[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code double[]} value.
*
* @param value The {@code double[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<double[], double[]> of(double... value) {
return new ForConstant<double[]>(value, PropertyDelegate.ForArrayType.DOUBLE);
}
Creates an annotation value for a String[]
value. Params: - value – The
String[]
value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for a {@code String[]} value.
*
* @param value The {@code String[]} value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<String[], String[]> of(String... value) {
return new ForConstant<String[]>(value, PropertyDelegate.ForArrayType.STRING);
}
Creates an annotation value for any constant value, i.e any primitive (wrapper) type, any primitive array type or any String
value or array. If no constant annotation type is provided, a runtime exception is thrown. Params: - value – The value to represent.
Returns: An appropriate annotation value.
/**
* Creates an annotation value for any constant value, i.e any primitive (wrapper) type,
* any primitive array type or any {@link String} value or array. If no constant annotation
* type is provided, a runtime exception is thrown.
*
* @param value The value to represent.
* @return An appropriate annotation value.
*/
public static AnnotationValue<?, ?> of(Object value) {
if (value instanceof Boolean) {
return of(((Boolean) value).booleanValue());
} else if (value instanceof Byte) {
return of(((Byte) value).byteValue());
} else if (value instanceof Short) {
return of(((Short) value).shortValue());
} else if (value instanceof Character) {
return of(((Character) value).charValue());
} else if (value instanceof Integer) {
return of(((Integer) value).intValue());
} else if (value instanceof Long) {
return of(((Long) value).longValue());
} else if (value instanceof Float) {
return of(((Float) value).floatValue());
} else if (value instanceof Double) {
return of(((Double) value).doubleValue());
} else if (value instanceof String) {
return of((String) value);
} else if (value instanceof boolean[]) {
return of((boolean[]) value);
} else if (value instanceof byte[]) {
return of((byte[]) value);
} else if (value instanceof short[]) {
return of((short[]) value);
} else if (value instanceof char[]) {
return of((char[]) value);
} else if (value instanceof int[]) {
return of((int[]) value);
} else if (value instanceof long[]) {
return of((long[]) value);
} else if (value instanceof float[]) {
return of((float[]) value);
} else if (value instanceof double[]) {
return of((double[]) value);
} else if (value instanceof String[]) {
return of((String[]) value);
} else {
throw new IllegalArgumentException("Not a constant annotation value: " + value);
}
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public U resolve() {
return value;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationValue.Loaded<U> load(ClassLoader classLoader) {
return new Loaded<U>(value, propertyDelegate);
}
@Override
public int hashCode() {
return propertyDelegate.hashCode(value);
}
@Override
public boolean equals(Object other) {
return this == other || other instanceof AnnotationValue<?, ?> && propertyDelegate.equals(value, ((AnnotationValue<?, ?>) other).resolve());
}
@Override
public String toString() {
return propertyDelegate.toString(value);
}
A property delegate for a constant annotation value.
/**
* A property delegate for a constant annotation value.
*/
protected interface PropertyDelegate {
Copies the provided value, if it is not immutable.
Params: - value – The value to copy.
Type parameters: - <S> – The value's type.
Returns: A copy of the provided instance or the provided value, if it is immutable.
/**
* Copies the provided value, if it is not immutable.
*
* @param value The value to copy.
* @param <S> The value's type.
* @return A copy of the provided instance or the provided value, if it is immutable.
*/
<S> S copy(S value);
Computes the value's hash code.
Params: - value – The value for which to compute the hash code.
Returns: The hash code of the provided value.
/**
* Computes the value's hash code.
*
* @param value The value for which to compute the hash code.
* @return The hash code of the provided value.
*/
int hashCode(Object value);
Determines if another value is equal to a constant annotation value.
Params: - self – The value that is represented as a constant annotation value.
- other – Any other value for which to determine equality.
Returns: true
if the provided value is equal to the represented value.
/**
* Determines if another value is equal to a constant annotation value.
*
* @param self The value that is represented as a constant annotation value.
* @param other Any other value for which to determine equality.
* @return {@code true} if the provided value is equal to the represented value.
*/
boolean equals(Object self, Object other);
Renders the supplied value as a String
. Params: - value – The value to render.
Returns: An appropriate String
representation of the provided value.
/**
* Renders the supplied value as a {@link String}.
*
* @param value The value to render.
* @return An appropriate {@link String} representation of the provided value.
*/
String toString(Object value);
A property delegate for a non-array type.
/**
* A property delegate for a non-array type.
*/
enum ForNonArrayType implements PropertyDelegate {
A property delegate for a boolean
value. /**
* A property delegate for a {@code boolean} value.
*/
BOOLEAN {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Boolean) value);
}
},
A property delegate for a byte
value. /**
* A property delegate for a {@code byte} value.
*/
BYTE {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Byte) value);
}
},
A property delegate for a short
value. /**
* A property delegate for a {@code short} value.
*/
SHORT {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Short) value);
}
},
A property delegate for a char
value. /**
* A property delegate for a {@code char} value.
*/
CHARACTER {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Character) value);
}
},
A property delegate for a int
value. /**
* A property delegate for a {@code int} value.
*/
INTEGER {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Integer) value);
}
},
A property delegate for a long
value. /**
* A property delegate for a {@code long} value.
*/
LONG {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Long) value);
}
},
A property delegate for a float
value. /**
* A property delegate for a {@code float} value.
*/
FLOAT {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Float) value);
}
},
A property delegate for a double
value. /**
* A property delegate for a {@code double} value.
*/
DOUBLE {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((Double) value);
}
},
A property delegate for a String
value. /**
* A property delegate for a {@link String} value.
*/
STRING {
{@inheritDoc} /** {@inheritDoc} */
public String toString(Object value) {
return RenderingDispatcher.CURRENT.toSourceString((String) value);
}
};
{@inheritDoc}
/**
* {@inheritDoc}
*/
public <S> S copy(S value) {
return value;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public int hashCode(Object value) {
return value.hashCode();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean equals(Object self, Object other) {
return self.equals(other);
}
}
A property delegate for an array type of a constant value.
/**
* A property delegate for an array type of a constant value.
*/
enum ForArrayType implements PropertyDelegate {
A property delegate for a boolean[]
value. /**
* A property delegate for a {@code boolean[]} value.
*/
BOOLEAN {
@Override
protected Object doCopy(Object value) {
return ((boolean[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((boolean[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof boolean[] && Arrays.equals((boolean[]) self, (boolean[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.BOOLEAN.toString(Array.getBoolean(array, index));
}
},
A property delegate for a byte[]
value. /**
* A property delegate for a {@code byte[]} value.
*/
BYTE {
@Override
protected Object doCopy(Object value) {
return ((byte[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((byte[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof byte[] && Arrays.equals((byte[]) self, (byte[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.BYTE.toString(Array.getByte(array, index));
}
},
A property delegate for a short[]
value. /**
* A property delegate for a {@code short[]} value.
*/
SHORT {
@Override
protected Object doCopy(Object value) {
return ((short[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((short[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof short[] && Arrays.equals((short[]) self, (short[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.SHORT.toString(Array.getShort(array, index));
}
},
A property delegate for a char[]
value. /**
* A property delegate for a {@code char[]} value.
*/
CHARACTER {
@Override
protected Object doCopy(Object value) {
return ((char[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((char[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof char[] && Arrays.equals((char[]) self, (char[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.CHARACTER.toString(Array.getChar(array, index));
}
},
A property delegate for a int[]
value. /**
* A property delegate for a {@code int[]} value.
*/
INTEGER {
@Override
protected Object doCopy(Object value) {
return ((int[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((int[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof int[] && Arrays.equals((int[]) self, (int[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.INTEGER.toString(Array.getInt(array, index));
}
},
A property delegate for a long[]
value. /**
* A property delegate for a {@code long[]} value.
*/
LONG {
@Override
protected Object doCopy(Object value) {
return ((long[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((long[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof long[] && Arrays.equals((long[]) self, (long[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.LONG.toString(Array.getLong(array, index));
}
},
A property delegate for a float[]
value. /**
* A property delegate for a {@code float[]} value.
*/
FLOAT {
@Override
protected Object doCopy(Object value) {
return ((float[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((float[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof float[] && Arrays.equals((float[]) self, (float[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.FLOAT.toString(Array.getFloat(array, index));
}
},
A property delegate for a double[]
value. /**
* A property delegate for a {@code double[]} value.
*/
DOUBLE {
@Override
protected Object doCopy(Object value) {
return ((double[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((double[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof double[] && Arrays.equals((double[]) self, (double[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.DOUBLE.toString(Array.getDouble(array, index));
}
},
A property delegate for a String[]
value. /**
* A property delegate for a {@code String[]} value.
*/
STRING {
@Override
protected Object doCopy(Object value) {
return ((String[]) value).clone();
}
{@inheritDoc} /** {@inheritDoc} */
public int hashCode(Object value) {
return Arrays.hashCode((String[]) value);
}
{@inheritDoc} /** {@inheritDoc} */
public boolean equals(Object self, Object other) {
return other instanceof String[] && Arrays.equals((String[]) self, (String[]) other);
}
@Override
protected String toString(Object array, int index) {
return ForNonArrayType.STRING.toString(Array.get(array, index));
}
};
{@inheritDoc}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public <S> S copy(S value) {
return (S) doCopy(value);
}
Creates a copy of the provided array.
Params: - value – The array to copy.
Returns: A shallow copy of the provided array.
/**
* Creates a copy of the provided array.
*
* @param value The array to copy.
* @return A shallow copy of the provided array.
*/
protected abstract Object doCopy(Object value);
{@inheritDoc}
/**
* {@inheritDoc}
*/
public String toString(Object value) {
List<String> elements = new ArrayList<String>(Array.getLength(value));
for (int index = 0; index < Array.getLength(value); index++) {
elements.add(toString(value, index));
}
return RenderingDispatcher.CURRENT.toSourceString(elements);
}
Renders the array element at the specified index.
Params: - array – The array for which an element should be rendered.
- index – The index of the array element to render.
Returns: A String
representation of the array element at the supplied index.
/**
* Renders the array element at the specified index.
*
* @param array The array for which an element should be rendered.
* @param index The index of the array element to render.
* @return A {@link String} representation of the array element at the supplied index.
*/
protected abstract String toString(Object array, int index);
}
}
Represents a trivial loaded value.
Type parameters: - <V> – The annotation properties type.
/**
* Represents a trivial loaded value.
*
* @param <V> The annotation properties type.
*/
protected static class Loaded<V> extends AnnotationValue.Loaded.AbstractBase<V> {
The represented value.
/**
* The represented value.
*/
private final V value;
The property delegate for the value's type.
/**
* The property delegate for the value's type.
*/
private final PropertyDelegate propertyDelegate;
Creates a new loaded representation of a constant value.
Params: - value – The represented value.
- propertyDelegate – The property delegate for the value's type.
/**
* Creates a new loaded representation of a constant value.
*
* @param value The represented value.
* @param propertyDelegate The property delegate for the value's type.
*/
protected Loaded(V value, PropertyDelegate propertyDelegate) {
this.value = value;
this.propertyDelegate = propertyDelegate;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.RESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public V resolve() {
return propertyDelegate.copy(value);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return propertyDelegate.equals(this.value, value);
}
@Override
public int hashCode() {
return propertyDelegate.hashCode(value);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue.Loaded<?>)) {
return false;
}
AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
return annotationValue.getState().isResolved() && propertyDelegate.equals(value, annotationValue.resolve());
}
@Override
public String toString() {
return propertyDelegate.toString(value);
}
}
}
A description of an Annotation
as a value of another annotation. Type parameters: - <U> – The type of the annotation.
/**
* A description of an {@link java.lang.annotation.Annotation} as a value of another annotation.
*
* @param <U> The type of the annotation.
*/
class ForAnnotationDescription<U extends Annotation> extends AbstractBase<AnnotationDescription, U> {
The annotation description that this value represents.
/**
* The annotation description that this value represents.
*/
private final AnnotationDescription annotationDescription;
Creates a new annotation value for a given annotation description.
Params: - annotationDescription – The annotation description that this value represents.
/**
* Creates a new annotation value for a given annotation description.
*
* @param annotationDescription The annotation description that this value represents.
*/
public ForAnnotationDescription(AnnotationDescription annotationDescription) {
this.annotationDescription = annotationDescription;
}
Creates an annotation value instance for describing the given annotation type and values.
Params: - annotationType – The annotation type.
- annotationValues – The values of the annotation.
Type parameters: - <V> – The type of the annotation.
Returns: An annotation value representing the given annotation.
/**
* Creates an annotation value instance for describing the given annotation type and values.
*
* @param annotationType The annotation type.
* @param annotationValues The values of the annotation.
* @param <V> The type of the annotation.
* @return An annotation value representing the given annotation.
*/
public static <V extends Annotation> AnnotationValue<AnnotationDescription, V> of(TypeDescription annotationType,
Map<String, ? extends AnnotationValue<?, ?>> annotationValues) {
return new ForAnnotationDescription<V>(new AnnotationDescription.Latent(annotationType, annotationValues));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationDescription resolve() {
return annotationDescription;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationValue.Loaded<U> load(ClassLoader classLoader) throws ClassNotFoundException {
@SuppressWarnings("unchecked")
Class<U> annotationType = (Class<U>) Class.forName(annotationDescription.getAnnotationType().getName(), false, classLoader);
return new Loaded<U>(annotationDescription.prepare(annotationType).load());
}
@Override
public int hashCode() {
return annotationDescription.hashCode();
}
@Override
public boolean equals(Object other) {
return this == other || other instanceof AnnotationValue<?, ?> && annotationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
}
@Override
public String toString() {
return annotationDescription.toString();
}
A loaded version of the described annotation.
Type parameters: - <V> – The annotation type.
/**
* A loaded version of the described annotation.
*
* @param <V> The annotation type.
*/
public static class Loaded<V extends Annotation> extends AnnotationValue.Loaded.AbstractBase<V> {
The loaded version of the represented annotation.
/**
* The loaded version of the represented annotation.
*/
private final V annotation;
Creates a representation of a loaded annotation.
Params: - annotation – The represented annotation.
/**
* Creates a representation of a loaded annotation.
*
* @param annotation The represented annotation.
*/
public Loaded(V annotation) {
this.annotation = annotation;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.RESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public V resolve() {
return annotation;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return annotation.equals(value);
}
@Override
public int hashCode() {
return annotation.hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue.Loaded<?>)) {
return false;
}
AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
return annotationValue.getState().isResolved() && annotation.equals(annotationValue.resolve());
}
@Override
public String toString() {
return annotation.toString();
}
}
Represents an annotation value which was attempted to ba loaded by a type that does not represent
an annotation value.
Note: Neither of Object.hashCode()
, Object.toString()
and Object.equals(Object)
are implemented specifically what resembles the way such exceptional states are represented in the Open JDK's annotation implementations.
/**
* <p>
* Represents an annotation value which was attempted to ba loaded by a type that does not represent
* an annotation value.
* </p>
* <p>
* <b>Note</b>: Neither of {@link Object#hashCode()}, {@link Object#toString()} and
* {@link java.lang.Object#equals(Object)} are implemented specifically what resembles the way
* such exceptional states are represented in the Open JDK's annotation implementations.
* </p>
*/
public static class IncompatibleRuntimeType extends AnnotationValue.Loaded.AbstractBase<Annotation> {
The incompatible runtime type which is not an annotation type.
/**
* The incompatible runtime type which is not an annotation type.
*/
private final Class<?> incompatibleType;
Creates a new representation for an annotation with an incompatible runtime type.
Params: - incompatibleType – The incompatible runtime type which is not an annotation type.
/**
* Creates a new representation for an annotation with an incompatible runtime type.
*
* @param incompatibleType The incompatible runtime type which is not an annotation type.
*/
public IncompatibleRuntimeType(Class<?> incompatibleType) {
this.incompatibleType = incompatibleType;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.UNRESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Annotation resolve() {
throw new IncompatibleClassChangeError("Not an annotation type: " + incompatibleType.toString());
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return false;
}
/* does intentionally not implement hashCode, equals and toString */
}
}
A description of an Enum
as a value of an annotation. Type parameters: - <U> – The type of the enumeration.
/**
* A description of an {@link java.lang.Enum} as a value of an annotation.
*
* @param <U> The type of the enumeration.
*/
class ForEnumerationDescription<U extends Enum<U>> extends AbstractBase<EnumerationDescription, U> {
The enumeration that is represented.
/**
* The enumeration that is represented.
*/
private final EnumerationDescription enumerationDescription;
Creates a new description of an annotation value for a given enumeration.
Params: - enumerationDescription – The enumeration that is to be represented.
/**
* Creates a new description of an annotation value for a given enumeration.
*
* @param enumerationDescription The enumeration that is to be represented.
*/
protected ForEnumerationDescription(EnumerationDescription enumerationDescription) {
this.enumerationDescription = enumerationDescription;
}
Creates a new annotation value for the given enumeration description.
Params: - value – The value to represent.
Type parameters: - <V> – The type of the represented enumeration.
Returns: An annotation value that describes the given enumeration.
/**
* Creates a new annotation value for the given enumeration description.
*
* @param value The value to represent.
* @param <V> The type of the represented enumeration.
* @return An annotation value that describes the given enumeration.
*/
public static <V extends Enum<V>> AnnotationValue<EnumerationDescription, V> of(EnumerationDescription value) {
return new ForEnumerationDescription<V>(value);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public EnumerationDescription resolve() {
return enumerationDescription;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationValue.Loaded<U> load(ClassLoader classLoader) throws ClassNotFoundException {
@SuppressWarnings("unchecked")
Class<U> enumerationType = (Class<U>) Class.forName(enumerationDescription.getEnumerationType().getName(), false, classLoader);
return new Loaded<U>(enumerationDescription.load(enumerationType));
}
@Override
public int hashCode() {
return enumerationDescription.hashCode();
}
@Override
public boolean equals(Object other) {
return this == other || other instanceof AnnotationValue<?, ?> && enumerationDescription.equals(((AnnotationValue<?, ?>) other).resolve());
}
@Override
public String toString() {
return enumerationDescription.toString();
}
A loaded representation of an enumeration value.
Type parameters: - <V> – The type of the represented enumeration.
/**
* A loaded representation of an enumeration value.
*
* @param <V> The type of the represented enumeration.
*/
public static class Loaded<V extends Enum<V>> extends AnnotationValue.Loaded.AbstractBase<V> {
The represented enumeration.
/**
* The represented enumeration.
*/
private final V enumeration;
Creates a loaded version of an enumeration description.
Params: - enumeration – The represented enumeration.
/**
* Creates a loaded version of an enumeration description.
*
* @param enumeration The represented enumeration.
*/
public Loaded(V enumeration) {
this.enumeration = enumeration;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.RESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public V resolve() {
return enumeration;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return enumeration.equals(value);
}
@Override
public int hashCode() {
return enumeration.hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue.Loaded<?>)) {
return false;
}
AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
return annotationValue.getState().isResolved() && enumeration.equals(annotationValue.resolve());
}
@Override
public String toString() {
return enumeration.toString();
}
}
Represents an annotation's enumeration value for a constant that does not exist for the runtime
enumeration type.
Note: Neither of Object.hashCode()
, Object.toString()
and Object.equals(Object)
are implemented specifically what resembles the way such exceptional states are represented in the Open JDK's annotation implementations.
/**
* <p>
* Represents an annotation's enumeration value for a constant that does not exist for the runtime
* enumeration type.
* </p>
* <p>
* <b>Note</b>: Neither of {@link Object#hashCode()}, {@link Object#toString()} and
* {@link java.lang.Object#equals(Object)} are implemented specifically what resembles the way
* such exceptional states are represented in the Open JDK's annotation implementations.
* </p>
*/
public static class UnknownRuntimeEnumeration extends AnnotationValue.Loaded.AbstractBase<Enum<?>> {
The loaded enumeration type.
/**
* The loaded enumeration type.
*/
private final Class<? extends Enum<?>> enumType;
The value for which no enumeration constant exists at runtime.
/**
* The value for which no enumeration constant exists at runtime.
*/
private final String value;
Creates a new representation for an unknown enumeration constant of an annotation.
Params: - enumType – The loaded enumeration type.
- value – The value for which no enumeration constant exists at runtime.
/**
* Creates a new representation for an unknown enumeration constant of an annotation.
*
* @param enumType The loaded enumeration type.
* @param value The value for which no enumeration constant exists at runtime.
*/
public UnknownRuntimeEnumeration(Class<? extends Enum<?>> enumType, String value) {
this.enumType = enumType;
this.value = value;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.UNRESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Enum<?> resolve() {
throw new EnumConstantNotPresentException(enumType, value);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return false;
}
/* hashCode, equals and toString are intentionally not implemented */
}
Represents an annotation's enumeration value for a runtime type that is not an enumeration type.
Note: Neither of Object.hashCode()
, Object.toString()
and Object.equals(Object)
are implemented specifically what resembles the way such exceptional states are represented in the Open JDK's annotation implementations.
/**
* <p>
* Represents an annotation's enumeration value for a runtime type that is not an enumeration type.
* </p>
* <p>
* <b>Note</b>: Neither of {@link Object#hashCode()}, {@link Object#toString()} and
* {@link java.lang.Object#equals(Object)} are implemented specifically what resembles the way
* such exceptional states are represented in the Open JDK's annotation implementations.
* </p>
*/
public static class IncompatibleRuntimeType extends AnnotationValue.Loaded.AbstractBase<Enum<?>> {
The runtime type which is not an enumeration type.
/**
* The runtime type which is not an enumeration type.
*/
private final Class<?> type;
Creates a new representation for an incompatible runtime type.
Params: - type – The runtime type which is not an enumeration type.
/**
* Creates a new representation for an incompatible runtime type.
*
* @param type The runtime type which is not an enumeration type.
*/
public IncompatibleRuntimeType(Class<?> type) {
this.type = type;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.UNRESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Enum<?> resolve() {
throw new IncompatibleClassChangeError("Not an enumeration type: " + type.toString());
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return false;
}
/* hashCode, equals and toString are intentionally not implemented */
}
}
A description of a Class
as a value of an annotation. Type parameters:
/**
* A description of a {@link java.lang.Class} as a value of an annotation.
*
* @param <U> The type of the {@link java.lang.Class} that is described.
*/
class ForTypeDescription<U extends Class<U>> extends AbstractBase<TypeDescription, U> {
Indicates to a class loading process that class initializers are not required to be executed when loading a type.
/**
* Indicates to a class loading process that class initializers are not required to be executed when loading a type.
*/
private static final boolean NO_INITIALIZATION = false;
A description of the represented type.
/**
* A description of the represented type.
*/
private final TypeDescription typeDescription;
Creates a new annotation value that represents a type.
Params: - typeDescription – The represented type.
/**
* Creates a new annotation value that represents a type.
*
* @param typeDescription The represented type.
*/
protected ForTypeDescription(TypeDescription typeDescription) {
this.typeDescription = typeDescription;
}
Creates an annotation value for representing the given type.
Params: - typeDescription – The type to represent.
Type parameters: - <V> – The represented type.
Returns: An annotation value that represents the given type.
/**
* Creates an annotation value for representing the given type.
*
* @param typeDescription The type to represent.
* @param <V> The represented type.
* @return An annotation value that represents the given type.
*/
public static <V extends Class<V>> AnnotationValue<TypeDescription, V> of(TypeDescription typeDescription) {
return new ForTypeDescription<V>(typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription resolve() {
return typeDescription;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public AnnotationValue.Loaded<U> load(ClassLoader classLoader) throws ClassNotFoundException {
return new Loaded<U>((U) Class.forName(typeDescription.getName(), NO_INITIALIZATION, classLoader));
}
@Override
public int hashCode() {
return typeDescription.hashCode();
}
@Override
public boolean equals(Object other) {
return this == other || other instanceof AnnotationValue<?, ?> && typeDescription.equals(((AnnotationValue<?, ?>) other).resolve());
}
@Override
public String toString() {
return RenderingDispatcher.CURRENT.toSourceString(typeDescription);
}
A loaded annotation value for a given type.
Type parameters: - <U> – The represented type.
/**
* A loaded annotation value for a given type.
*
* @param <U> The represented type.
*/
protected static class Loaded<U extends Class<U>> extends AnnotationValue.Loaded.AbstractBase<U> {
The represented type.
/**
* The represented type.
*/
private final U type;
Creates a new loaded annotation value for a given type.
Params: - type – The represented type.
/**
* Creates a new loaded annotation value for a given type.
*
* @param type The represented type.
*/
public Loaded(U type) {
this.type = type;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
return State.RESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public U resolve() {
return type;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
return type.equals(value);
}
@Override
public int hashCode() {
return type.hashCode();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue.Loaded<?>)) {
return false;
}
AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
return annotationValue.getState().isResolved() && type.equals(annotationValue.resolve());
}
@Override
public String toString() {
return RenderingDispatcher.CURRENT.toSourceString(TypeDescription.ForLoadedType.of(type));
}
}
}
Describes a complex array that is the value of an annotation. Complex arrays are arrays that might trigger the loading of user-defined types, i.e. Class
, Annotation
and Enum
instances. Type parameters:
/**
* Describes a complex array that is the value of an annotation. Complex arrays are arrays that might trigger the loading
* of user-defined types, i.e. {@link java.lang.Class}, {@link java.lang.annotation.Annotation} and {@link java.lang.Enum}
* instances.
*
* @param <U> The component type of the annotation's value when it is not loaded.
* @param <V> The component type of the annotation's value when it is loaded.
*/
class ForDescriptionArray<U, V> extends AbstractBase<U[], V[]> {
The component type for arrays containing unloaded versions of the annotation array's values.
/**
* The component type for arrays containing unloaded versions of the annotation array's values.
*/
private final Class<?> unloadedComponentType;
A description of the component type when it is loaded.
/**
* A description of the component type when it is loaded.
*/
private final TypeDescription componentType;
A list of values of the array elements.
/**
* A list of values of the array elements.
*/
private final List<? extends AnnotationValue<?, ?>> values;
Creates a new complex array.
Params: - unloadedComponentType – The component type for arrays containing unloaded versions of the annotation array's values.
- componentType – A description of the component type when it is loaded.
- values – A list of values of the array elements.
/**
* Creates a new complex array.
*
* @param unloadedComponentType The component type for arrays containing unloaded versions of the annotation array's values.
* @param componentType A description of the component type when it is loaded.
* @param values A list of values of the array elements.
*/
protected ForDescriptionArray(Class<?> unloadedComponentType,
TypeDescription componentType,
List<? extends AnnotationValue<?, ?>> values) {
this.unloadedComponentType = unloadedComponentType;
this.componentType = componentType;
this.values = values;
}
Creates a new complex array of enumeration descriptions.
Params: - enumerationType – A description of the type of the enumeration.
- enumerationDescription – An array of enumeration descriptions.
Type parameters: - <W> – The type of the enumeration.
Returns: A description of the array of enumeration values.
/**
* Creates a new complex array of enumeration descriptions.
*
* @param enumerationType A description of the type of the enumeration.
* @param enumerationDescription An array of enumeration descriptions.
* @param <W> The type of the enumeration.
* @return A description of the array of enumeration values.
*/
public static <W extends Enum<W>> AnnotationValue<EnumerationDescription[], W[]> of(TypeDescription enumerationType,
EnumerationDescription[] enumerationDescription) {
List<AnnotationValue<EnumerationDescription, W>> values = new ArrayList<AnnotationValue<EnumerationDescription, W>>(enumerationDescription.length);
for (EnumerationDescription value : enumerationDescription) {
if (!value.getEnumerationType().equals(enumerationType)) {
throw new IllegalArgumentException(value + " is not of " + enumerationType);
}
values.add(ForEnumerationDescription.<W>of(value));
}
return new ForDescriptionArray<EnumerationDescription, W>(EnumerationDescription.class, enumerationType, values);
}
Creates a new complex array of annotation descriptions.
Params: - annotationType – A description of the type of the annotation.
- annotationDescription – An array of annotation descriptions.
Type parameters: - <W> – The type of the annotation.
Returns: A description of the array of enumeration values.
/**
* Creates a new complex array of annotation descriptions.
*
* @param annotationType A description of the type of the annotation.
* @param annotationDescription An array of annotation descriptions.
* @param <W> The type of the annotation.
* @return A description of the array of enumeration values.
*/
public static <W extends Annotation> AnnotationValue<AnnotationDescription[], W[]> of(TypeDescription annotationType,
AnnotationDescription[] annotationDescription) {
List<AnnotationValue<AnnotationDescription, W>> values = new ArrayList<AnnotationValue<AnnotationDescription, W>>(annotationDescription.length);
for (AnnotationDescription value : annotationDescription) {
if (!value.getAnnotationType().equals(annotationType)) {
throw new IllegalArgumentException(value + " is not of " + annotationType);
}
values.add(new ForAnnotationDescription<W>(value));
}
return new ForDescriptionArray<AnnotationDescription, W>(AnnotationDescription.class, annotationType, values);
}
Creates a new complex array of annotation descriptions.
Params: - typeDescription – A description of the types contained in the array.
Returns: A description of the array of enumeration values.
/**
* Creates a new complex array of annotation descriptions.
*
* @param typeDescription A description of the types contained in the array.
* @return A description of the array of enumeration values.
*/
@SuppressWarnings("unchecked")
public static AnnotationValue<TypeDescription[], Class<?>[]> of(TypeDescription[] typeDescription) {
List<AnnotationValue<TypeDescription, Class<?>>> values = new ArrayList<AnnotationValue<TypeDescription, Class<?>>>(typeDescription.length);
for (TypeDescription value : typeDescription) {
values.add((AnnotationValue) ForTypeDescription.<Class>of(value));
}
return new ForDescriptionArray<TypeDescription, Class<?>>(TypeDescription.class, TypeDescription.CLASS, values);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public U[] resolve() {
@SuppressWarnings("unchecked")
U[] resolved = (U[]) Array.newInstance(unloadedComponentType, values.size());
int index = 0;
for (AnnotationValue<?, ?> value : values) {
Array.set(resolved, index++, value.resolve());
}
return resolved;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public AnnotationValue.Loaded<V[]> load(ClassLoader classLoader) throws ClassNotFoundException {
List<AnnotationValue.Loaded<?>> values = new ArrayList<AnnotationValue.Loaded<?>>(this.values.size());
for (AnnotationValue<?, ?> value : this.values) {
values.add(value.load(classLoader));
}
return new Loaded<V>((Class<V>) Class.forName(componentType.getName(), false, classLoader), values);
}
@Override
public int hashCode() {
int result = 1;
for (AnnotationValue<?, ?> value : values) {
result = 31 * result + value.hashCode();
}
return result;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue<?, ?>)) {
return false;
}
AnnotationValue<?, ?> annotationValue = (AnnotationValue<?, ?>) other;
Object value = annotationValue.resolve();
if (!(value instanceof Object[])) {
return false;
}
Object[] arrayValue = (Object[]) value;
if (values.size() != arrayValue.length) {
return false;
}
Iterator<? extends AnnotationValue<?, ?>> iterator = values.iterator();
for (Object aValue : arrayValue) {
AnnotationValue<?, ?> self = iterator.next();
if (!self.resolve().equals(aValue)) {
return false;
}
}
return true;
}
@Override
public String toString() {
return RenderingDispatcher.CURRENT.toSourceString(values);
}
Represents a loaded complex array.
Type parameters: - <W> – The component type of the loaded array.
/**
* Represents a loaded complex array.
*
* @param <W> The component type of the loaded array.
*/
protected static class Loaded<W> extends AnnotationValue.Loaded.AbstractBase<W[]> {
The loaded component type of the array.
/**
* The loaded component type of the array.
*/
private final Class<W> componentType;
A list of loaded values that the represented array contains.
/**
* A list of loaded values that the represented array contains.
*/
private final List<AnnotationValue.Loaded<?>> values;
Creates a new loaded value representing a complex array.
Params: - componentType – The loaded component type of the array.
- values – A list of loaded values that the represented array contains.
/**
* Creates a new loaded value representing a complex array.
*
* @param componentType The loaded component type of the array.
* @param values A list of loaded values that the represented array contains.
*/
protected Loaded(Class<W> componentType, List<AnnotationValue.Loaded<?>> values) {
this.componentType = componentType;
this.values = values;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public State getState() {
for (AnnotationValue.Loaded<?> value : values) {
if (!value.getState().isResolved()) {
return State.UNRESOLVED;
}
}
return State.RESOLVED;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public W[] resolve() {
@SuppressWarnings("unchecked")
W[] array = (W[]) Array.newInstance(componentType, values.size());
int index = 0;
for (AnnotationValue.Loaded<?> annotationValue : values) {
Array.set(array, index++, annotationValue.resolve());
}
return array;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean represents(Object value) {
if (!(value instanceof Object[])) return false;
if (value.getClass().getComponentType() != componentType) return false;
Object[] array = (Object[]) value;
if (values.size() != array.length) return false;
Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
for (Object aValue : array) {
AnnotationValue.Loaded<?> self = iterator.next();
if (!self.represents(aValue)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
int result = 1;
for (AnnotationValue.Loaded<?> value : values) {
result = 31 * result + value.hashCode();
}
return result;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (!(other instanceof AnnotationValue.Loaded<?>)) {
return false;
}
AnnotationValue.Loaded<?> annotationValue = (AnnotationValue.Loaded<?>) other;
if (!annotationValue.getState().isResolved()) {
return false;
}
Object value = annotationValue.resolve();
if (!(value instanceof Object[])) {
return false;
}
Object[] arrayValue = (Object[]) value;
if (values.size() != arrayValue.length) {
return false;
}
Iterator<AnnotationValue.Loaded<?>> iterator = values.iterator();
for (Object aValue : arrayValue) {
AnnotationValue.Loaded<?> self = iterator.next();
if (!self.getState().isResolved() || !self.resolve().equals(aValue)) {
return false;
}
}
return true;
}
@Override
public String toString() {
return RenderingDispatcher.CURRENT.toSourceString(values);
}
}
}
}