package io.micronaut.inject.annotation;
import io.micronaut.context.exceptions.ConfigurationException;
import io.micronaut.core.annotation.*;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.reflect.ClassUtils;
import io.micronaut.core.reflect.ReflectionUtils;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.core.value.OptionalValues;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
@Internal
public class DefaultAnnotationMetadata extends AbstractAnnotationMetadata implements AnnotationMetadata, Cloneable, EnvironmentAnnotationMetadata {
static {
ConversionService.SHARED.addConverter(io.micronaut.core.annotation.AnnotationValue.class, Annotation.class, (object, targetType, context) -> {
Optional<Class> annotationClass = ClassUtils.forName(object.getAnnotationName(), targetType.getClassLoader());
return annotationClass.map(aClass -> AnnotationMetadataSupport.buildAnnotation(aClass, object));
});
ConversionService.SHARED.addConverter(io.micronaut.core.annotation.AnnotationValue[].class, Object[].class, (object, targetType, context) -> {
List result = new ArrayList();
Class annotationClass = null;
for (io.micronaut.core.annotation.AnnotationValue annotationValue : object) {
if (annotationClass == null) {
Optional<Class> aClass = ClassUtils.forName(annotationValue.getAnnotationName(), targetType.getClassLoader());
if (!aClass.isPresent()) {
break;
}
annotationClass = aClass.get();
}
Annotation annotation = AnnotationMetadataSupport.buildAnnotation(annotationClass, annotationValue);
result.add(annotation);
}
if (!result.isEmpty()) {
return Optional.of(result.toArray((Object[]) Array.newInstance(annotationClass, result.size())));
}
return Optional.empty();
});
}
@Nullable
Map<String, Map<CharSequence, Object>> declaredAnnotations;
@Nullable
Map<String, Map<CharSequence, Object>> allAnnotations;
@Nullable
Map<String, Map<CharSequence, Object>> declaredStereotypes;
@Nullable
Map<String, Map<CharSequence, Object>> allStereotypes;
@Nullable
Map<String, List<String>> annotationsByStereotype;
@Nullable
Map<String, Map<CharSequence, Object>> annotationDefaultValues;
private Map<Class, List> annotationValuesByType = new ConcurrentHashMap<>(2);
private Map<String, String> repeated = null;
private Set<String> sourceRetentionAnnotations;
@Internal
protected DefaultAnnotationMetadata() {
}
@Internal
@UsedByGeneratedCode
public DefaultAnnotationMetadata(
@Nullable Map<String, Map<CharSequence, Object>> declaredAnnotations,
@Nullable Map<String, Map<CharSequence, Object>> declaredStereotypes,
@Nullable Map<String, Map<CharSequence, Object>> allStereotypes,
@Nullable Map<String, Map<CharSequence, Object>> allAnnotations,
@Nullable Map<String, List<String>> annotationsByStereotype) {
super(declaredAnnotations, allAnnotations);
this.declaredAnnotations = declaredAnnotations;
this.declaredStereotypes = declaredStereotypes;
this.allStereotypes = allStereotypes;
this.allAnnotations = allAnnotations;
this.annotationsByStereotype = annotationsByStereotype;
}
@Internal
Set<String> getSourceRetentionAnnotations() {
if (sourceRetentionAnnotations != null) {
return Collections.unmodifiableSet(sourceRetentionAnnotations);
}
return Collections.emptySet();
}
@NonNull
@Override
public Map<String, Object> getDefaultValues(@NonNull String annotation) {
ArgumentUtils.requireNonNull("annotation", annotation);
return AnnotationMetadataSupport.getDefaultValues(annotation);
}
@Override
public boolean isPresent(@NonNull String annotation, @NonNull String member) {
boolean isPresent = false;
if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = allAnnotations.get(annotation);
if (values != null) {
isPresent = values.containsKey(member);
} else if (allStereotypes != null) {
values = allStereotypes.get(annotation);
if (values != null) {
isPresent = values.containsKey(member);
}
}
}
return isPresent;
}
@Override
public <E extends Enum> Optional<E> enumValue(@NonNull String annotation, Class<E> enumType) {
return enumValue(annotation, VALUE_MEMBER, enumType, null);
}
@Override
public <E extends Enum> Optional<E> enumValue(@NonNull String annotation, @NonNull String member, Class<E> enumType) {
return enumValue(annotation, member, enumType, null);
}
@Override
public <E extends Enum> Optional<E> enumValue(@NonNull Class<? extends Annotation> annotation, Class<E> enumType) {
return enumValue(annotation, VALUE_MEMBER, enumType);
}
@Override
public <E extends Enum> Optional<E> enumValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Class<E> enumType) {
return enumValue(annotation, member, enumType, null);
}
@Override
@Internal
public <E extends Enum> Optional<E> enumValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Class<E> enumType, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).enumValue(member, enumType, valueMapper);
}
return Optional.empty();
} else {
return enumValue(annotation.getName(), member, enumType, valueMapper);
}
}
@Override
public <E extends Enum> E[] enumValues(@NonNull String annotation, Class<E> enumType) {
return enumValues(annotation, VALUE_MEMBER, enumType, null);
}
@Override
public <E extends Enum> E[] enumValues(@NonNull String annotation, @NonNull String member, Class<E> enumType) {
return enumValues(annotation, member, enumType, null);
}
@Override
public <E extends Enum> E[] enumValues(@NonNull Class<? extends Annotation> annotation, Class<E> enumType) {
return enumValues(annotation, VALUE_MEMBER, enumType, null);
}
@Override
public <E extends Enum> E[] enumValues(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Class<E> enumType) {
return enumValues(annotation, member, enumType, null);
}
@Override
public <E extends Enum> E[] enumValues(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Class<E> enumType, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("enumType", enumType);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawValue(repeatable.value().getName(), member);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).enumValues(member, enumType);
}
return (E[]) Array.newInstance(enumType, 0);
} else {
Object v = getRawValue(annotation.getName(), member);
return AnnotationValue.resolveEnumValues(enumType, v);
}
}
@Override
public <E extends Enum> E[] enumValues(@NonNull String annotation, @NonNull String member, Class<E> enumType, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("enumType", enumType);
Object v = getRawValue(annotation, member);
return AnnotationValue.resolveEnumValues(enumType, v);
}
@Override
@Internal
public <E extends Enum> Optional<E> enumValue(@NonNull String annotation, @NonNull String member, Class<E> enumType, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
return enumValueOf(enumType, rawValue);
}
private <E extends Enum> Optional<E> enumValueOf(Class<E> enumType, Object rawValue) {
if (rawValue != null) {
if (enumType.isInstance(rawValue)) {
return Optional.of((E) rawValue);
} else {
try {
return Optional.of((E) Enum.valueOf(enumType, rawValue.toString()));
} catch (Exception e) {
return Optional.empty();
}
}
}
return Optional.empty();
}
@Override
public <T> Class<T>[] classValues(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
Object rawSingleValue = getRawValue(annotation, member);
Class<T>[] classes = (Class<T>[]) AnnotationValue.resolveClassValues(rawSingleValue);
if (classes != null) {
return classes;
}
return ReflectionUtils.EMPTY_CLASS_ARRAY;
}
@Override
public <T> Class<T>[] classValues(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), member, null);
if (v instanceof AnnotationValue) {
Class<?>[] classes = ((AnnotationValue<?>) v).classValues(member);
return (Class<T>[]) classes;
}
return ReflectionUtils.EMPTY_CLASS_ARRAY;
} else {
return classValues(annotation.getName(), member);
}
}
@NonNull
@Override
public Optional<Class> classValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return classValue(annotation, member, null);
}
@Override
public Optional<Class> classValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), member, valueMapper);
if (v instanceof AnnotationValue) {
return (Optional) ((AnnotationValue<?>) v).classValue(member, valueMapper);
}
return Optional.empty();
} else {
return classValue(annotation.getName(), member, valueMapper);
}
}
@NonNull
@Override
public Optional<Class> classValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return classValue(annotation, member, null);
}
@Override
@Internal
public Optional<Class> classValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof AnnotationClassValue) {
return ((AnnotationClassValue) rawValue).getType();
} else if (rawValue instanceof Class) {
return Optional.of((Class) rawValue);
} else if (rawValue != null) {
return ConversionService.SHARED.convert(rawValue, Class.class);
}
return Optional.empty();
}
@NonNull
@Override
public OptionalInt intValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return intValue(annotation, member, null);
}
@NonNull
@Override
public OptionalInt intValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return intValue(annotation, member, null);
}
@Override
@Internal
public OptionalInt intValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).intValue(member, valueMapper);
}
return OptionalInt.empty();
} else {
return intValue(annotation.getName(), member, valueMapper);
}
}
@Override
public Optional<Boolean> booleanValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return booleanValue(annotation, member, null);
}
@Override
public Optional<Boolean> booleanValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return booleanValue(annotation, member, null);
}
@Override
public Optional<Boolean> booleanValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, null);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).booleanValue(member, valueMapper);
}
return Optional.empty();
} else {
return booleanValue(annotation.getName(), member, valueMapper);
}
}
@Override
@NonNull
public Optional<Boolean> booleanValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof Boolean) {
return Optional.of((Boolean) rawValue);
} else if (rawValue != null) {
return Optional.of(StringUtils.isTrue(rawValue.toString()));
}
return Optional.empty();
}
@NonNull
@Override
public OptionalLong longValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return longValue(annotation, member, null);
}
@NonNull
@Override
public OptionalLong longValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return longValue(annotation, member, null);
}
@Override
@Internal
public OptionalLong longValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).longValue(member, valueMapper);
}
return OptionalLong.empty();
} else {
return longValue(annotation.getName(), member, valueMapper);
}
}
@Override
@NonNull
public OptionalLong longValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof Number) {
return OptionalLong.of(((Number) rawValue).longValue());
} else if (rawValue instanceof CharSequence) {
final String str = rawValue.toString();
if (StringUtils.isNotEmpty(str)) {
try {
final long i = Long.parseLong(str);
return OptionalLong.of(i);
} catch (NumberFormatException e) {
throw new ConfigurationException("Invalid value [" + str + "] of [" + member + "] of annotation [" + annotation + "]: " + e.getMessage(), e);
}
}
}
return OptionalLong.empty();
}
@Override
@NonNull
public OptionalInt intValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof Number) {
return OptionalInt.of(((Number) rawValue).intValue());
} else if (rawValue instanceof CharSequence) {
final String str = rawValue.toString();
if (StringUtils.isNotEmpty(str)) {
try {
final int i = Integer.parseInt(str);
return OptionalInt.of(i);
} catch (NumberFormatException e) {
throw new ConfigurationException("Invalid value [" + str + "] of [" + member + "] of annotation [" + annotation + "]: " + e.getMessage(), e);
}
}
}
return OptionalInt.empty();
}
@NonNull
@Override
public Optional<String> stringValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return stringValue(annotation, member, null);
}
@Override
public Optional<String> stringValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).stringValue(member, valueMapper);
}
return Optional.empty();
} else {
return stringValue(annotation.getName(), member, valueMapper);
}
}
@NonNull
@Override
public String[] stringValues(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return stringValues(annotation, member, null);
}
@Override
@NonNull
public String[] stringValues(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawValue(repeatable.value().getName(), member);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).stringValues(member, valueMapper);
}
return StringUtils.EMPTY_STRING_ARRAY;
} else {
Object v = getRawValue(annotation.getName(), member);
String[] strings = AnnotationValue.resolveStringValues(v, valueMapper);
return strings != null ? strings : StringUtils.EMPTY_STRING_ARRAY;
}
}
@NonNull
@Override
public Optional<String> stringValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return stringValue(annotation, member, null);
}
@Override
@NonNull
public Optional<String> stringValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof CharSequence) {
return Optional.of(rawValue.toString());
} else if (rawValue instanceof Class) {
String name = ((Class) rawValue).getName();
return Optional.of(name);
} else if (rawValue != null) {
return Optional.of(rawValue.toString());
}
return Optional.empty();
}
@Override
public boolean isTrue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return isTrue(annotation, member, null);
}
@Override
public boolean isTrue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).isTrue(member, valueMapper);
}
return false;
} else {
return isTrue(annotation.getName(), member, valueMapper);
}
}
@Override
public boolean isTrue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return isTrue(annotation, member, null);
}
@Override
public boolean isTrue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof Boolean) {
return (Boolean) rawValue;
} else if (rawValue != null) {
String booleanString = rawValue.toString().toLowerCase(Locale.ENGLISH);
return StringUtils.isTrue(booleanString);
}
return false;
}
@Override
public boolean isFalse(@NonNull String annotation, @NonNull String member) {
return !isTrue(annotation, member);
}
@NonNull
@Override
public OptionalDouble doubleValue(@NonNull String annotation, @NonNull String member) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
return doubleValue(annotation, member, null);
}
@NonNull
@Override
public OptionalDouble doubleValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member) {
return doubleValue(annotation, member, null);
}
@Override
@Internal
public OptionalDouble doubleValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
if (repeatable != null) {
Object v = getRawSingleValue(repeatable.value().getName(), VALUE_MEMBER, valueMapper);
if (v instanceof AnnotationValue) {
return ((AnnotationValue<?>) v).doubleValue(member, valueMapper);
}
return OptionalDouble.empty();
} else {
return doubleValue(annotation.getName(), member);
}
}
@Override
@NonNull
@Internal
public OptionalDouble doubleValue(@NonNull String annotation, @NonNull String member, Function<Object, Object> valueMapper) {
Object rawValue = getRawSingleValue(annotation, member, valueMapper);
if (rawValue instanceof Number) {
return OptionalDouble.of(((Number) rawValue).doubleValue());
} else if (rawValue instanceof CharSequence) {
final String str = rawValue.toString();
if (StringUtils.isNotEmpty(str)) {
try {
final double i = Double.parseDouble(str);
return OptionalDouble.of(i);
} catch (NumberFormatException e) {
throw new ConfigurationException("Invalid value [" + str + "] of member [" + member + "] of annotation [" + annotation + "]: " + e.getMessage(), e);
}
}
}
return OptionalDouble.empty();
}
@Override
public @NonNull
<T> Optional<T> getValue(@NonNull Class<? extends Annotation> annotation, @NonNull String member, @NonNull Class<T> requiredType) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
ArgumentUtils.requireNonNull("requiredType", requiredType);
final Repeatable repeatable = annotation.getAnnotation(Repeatable.class);
final boolean isRepeatable = repeatable != null;
if (isRepeatable) {
List<? extends AnnotationValue<? extends Annotation>> values = getAnnotationValuesByType(annotation);
if (!values.isEmpty()) {
return values.iterator().next().get(member, requiredType);
} else {
return Optional.empty();
}
} else {
return getValue(annotation.getName(), member, requiredType);
}
}
@Override
public @NonNull
<T> Optional<T> getValue(@NonNull String annotation, @NonNull String member, @NonNull Argument<T> requiredType) {
return getValue(annotation, member, requiredType, null);
}
@Override
@NonNull
public <T> Optional<T> getValue(@NonNull String annotation, @NonNull String member, @NonNull Argument<T> requiredType, @Nullable Function<Object, Object> valueMapper) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
ArgumentUtils.requireNonNull("requiredType", requiredType);
Optional<T> resolved = Optional.empty();
if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = allAnnotations.get(annotation);
if (values != null) {
Object rawValue = values.get(member);
if (rawValue != null) {
if (valueMapper != null) {
rawValue = valueMapper.apply(rawValue);
}
resolved = ConversionService.SHARED.convert(
rawValue, requiredType
);
}
} else if (allStereotypes != null) {
values = allStereotypes.get(annotation);
if (values != null) {
Object rawValue = values.get(member);
if (rawValue != null) {
if (valueMapper != null) {
rawValue = valueMapper.apply(rawValue);
}
resolved = ConversionService.SHARED.convert(
rawValue, requiredType
);
}
}
}
}
if (!resolved.isPresent() && hasStereotype(annotation)) {
return getDefaultValue(annotation, member, requiredType);
}
return resolved;
}
@Override
public @NonNull
<T> Optional<T> getDefaultValue(@NonNull String annotation, @NonNull String member, @NonNull Class<T> requiredType) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
ArgumentUtils.requireNonNull("requiredType", requiredType);
Map<String, Object> defaultValues = AnnotationMetadataSupport.getDefaultValues(annotation);
if (defaultValues.containsKey(member)) {
final Object v = defaultValues.get(member);
if (requiredType.isInstance(v)) {
return (Optional<T>) Optional.of(v);
} else {
return ConversionService.SHARED.convert(v, requiredType);
}
}
return Optional.empty();
}
@SuppressWarnings("unchecked")
@Override
public @NonNull
<T extends Annotation> List<AnnotationValue<T>> getAnnotationValuesByType(@Nullable Class<T> annotationType) {
if (annotationType != null) {
List<AnnotationValue<T>> results = annotationValuesByType.get(annotationType);
if (results == null) {
results = resolveAnnotationValuesByType(annotationType, allAnnotations, allStereotypes);
if (results != null) {
return results;
} else if (allAnnotations != null) {
final Map<CharSequence, Object> values = allAnnotations.get(annotationType.getName());
if (values != null) {
results = Collections.singletonList(new AnnotationValue<>(annotationType.getName(), values));
}
}
if (results == null) {
results = Collections.emptyList();
}
annotationValuesByType.put(annotationType, results);
}
return results;
}
return Collections.emptyList();
}
@Override
public @NonNull
<T extends Annotation> List<AnnotationValue<T>> getDeclaredAnnotationValuesByType(@NonNull Class<T> annotationType) {
if (annotationType != null) {
Map<String, Map<CharSequence, Object>> sourceAnnotations = this.declaredAnnotations;
Map<String, Map<CharSequence, Object>> sourceStereotypes = this.declaredStereotypes;
List<AnnotationValue<T>> results = resolveAnnotationValuesByType(annotationType, sourceAnnotations, sourceStereotypes);
if (results != null) {
return results;
}
}
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
@Override
public <T extends Annotation> T[] synthesizeAnnotationsByType(@NonNull Class<T> annotationClass) {
if (annotationClass != null) {
List<AnnotationValue<T>> values = getAnnotationValuesByType(annotationClass);
return values.stream()
.map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, entries))
.toArray(value -> (T[]) Array.newInstance(annotationClass, value));
}
return (T[]) AnnotationUtil.ZERO_ANNOTATIONS;
}
@Override
public <T extends Annotation> T[] synthesizeDeclaredAnnotationsByType(@NonNull Class<T> annotationClass) {
if (annotationClass != null) {
List<AnnotationValue<T>> values = getAnnotationValuesByType(annotationClass);
return values.stream()
.map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, entries))
.toArray(value -> (T[]) Array.newInstance(annotationClass, value));
}
return (T[]) AnnotationUtil.ZERO_ANNOTATIONS;
}
@Override
public boolean isEmpty() {
return allAnnotations == null || allAnnotations.isEmpty();
}
@Override
public boolean hasDeclaredAnnotation(String annotation) {
return declaredAnnotations != null && StringUtils.isNotEmpty(annotation) && declaredAnnotations.containsKey(annotation);
}
@Override
public boolean hasAnnotation(String annotation) {
return hasDeclaredAnnotation(annotation) || (allAnnotations != null && StringUtils.isNotEmpty(annotation) && allAnnotations.containsKey(annotation));
}
@Override
public boolean hasStereotype(String annotation) {
return hasAnnotation(annotation) || (allStereotypes != null && StringUtils.isNotEmpty(annotation) && allStereotypes.containsKey(annotation));
}
@Override
public boolean hasDeclaredStereotype(String annotation) {
return hasDeclaredAnnotation(annotation) || (declaredStereotypes != null && StringUtils.isNotEmpty(annotation) && declaredStereotypes.containsKey(annotation));
}
@NonNull
@Override
public Optional<Class<? extends Annotation>> getAnnotationTypeByStereotype(@Nullable String stereotype) {
if (stereotype != null) {
if (annotationsByStereotype != null) {
List<String> annotations = annotationsByStereotype.get(stereotype);
if (CollectionUtils.isNotEmpty(annotations)) {
return getAnnotationType(annotations.get(0));
}
}
if (allAnnotations != null && allAnnotations.containsKey(stereotype)) {
return getAnnotationType(stereotype);
}
if (declaredAnnotations != null && declaredAnnotations.containsKey(stereotype)) {
return getAnnotationType(stereotype);
}
}
return Optional.empty();
}
@NonNull
@Override
public Optional<String> getAnnotationNameByStereotype(@Nullable String stereotype) {
if (stereotype != null) {
if (annotationsByStereotype != null) {
List<String> annotations = annotationsByStereotype.get(stereotype);
if (CollectionUtils.isNotEmpty(annotations)) {
return Optional.of(annotations.get(0));
}
}
if (allAnnotations != null && allAnnotations.containsKey(stereotype)) {
return Optional.of(stereotype);
}
if (declaredAnnotations != null && declaredAnnotations.containsKey(stereotype)) {
return Optional.of(stereotype);
}
}
return Optional.empty();
}
@Override
public @NonNull
List<String> getAnnotationNamesByStereotype(@Nullable String stereotype) {
if (stereotype == null) {
return Collections.emptyList();
}
if (annotationsByStereotype != null) {
List<String> annotations = annotationsByStereotype.get(stereotype);
if (annotations != null) {
return Collections.unmodifiableList(annotations);
}
}
if (allAnnotations != null && allAnnotations.containsKey(stereotype)) {
return StringUtils.internListOf(stereotype);
}
if (declaredAnnotations != null && declaredAnnotations.containsKey(stereotype)) {
return StringUtils.internListOf(stereotype);
}
return Collections.emptyList();
}
@Override
public @NonNull
Set<String> getAnnotationNames() {
if (allAnnotations != null) {
return allAnnotations.keySet();
}
return Collections.emptySet();
}
@Override
public @NonNull
Set<String> getDeclaredAnnotationNames() {
if (declaredAnnotations != null) {
return declaredAnnotations.keySet();
}
return Collections.emptySet();
}
@Override
public @NonNull
List<String> getDeclaredAnnotationNamesByStereotype(@Nullable String stereotype) {
if (stereotype == null) {
return Collections.emptyList();
}
if (annotationsByStereotype != null) {
List<String> annotations = annotationsByStereotype.get(stereotype);
if (annotations != null) {
annotations = new ArrayList<>(annotations);
if (declaredAnnotations != null) {
annotations.removeIf(s -> !declaredAnnotations.containsKey(s));
return Collections.unmodifiableList(annotations);
} else {
return Collections.emptyList();
}
}
}
if (declaredAnnotations != null && declaredAnnotations.containsKey(stereotype)) {
return StringUtils.internListOf(stereotype);
}
return Collections.emptyList();
}
@Override
public @NonNull
Optional<Class<? extends Annotation>> getAnnotationType(@NonNull String name) {
return AnnotationMetadataSupport.getAnnotationType(name);
}
@Override
public @NonNull
Optional<Class<? extends Annotation>> getAnnotationType(@NonNull String name, @NonNull ClassLoader classLoader) {
return AnnotationMetadataSupport.getAnnotationType(name, classLoader);
}
@SuppressWarnings("Duplicates")
@Override
public @NonNull
<T extends Annotation> Optional<AnnotationValue<T>> findAnnotation(@NonNull String annotation) {
ArgumentUtils.requireNonNull("annotation", annotation);
if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = allAnnotations.get(annotation);
if (values != null) {
return Optional.of(new AnnotationValue<>(annotation, values, AnnotationMetadataSupport.getDefaultValues(annotation)));
} else if (allStereotypes != null) {
values = allStereotypes.get(annotation);
if (values != null) {
return Optional.of(new AnnotationValue<>(annotation, values, AnnotationMetadataSupport.getDefaultValues(annotation)));
}
}
}
return Optional.empty();
}
@SuppressWarnings("Duplicates")
@Override
public @NonNull
<T extends Annotation> Optional<AnnotationValue<T>> findDeclaredAnnotation(@NonNull String annotation) {
ArgumentUtils.requireNonNull("annotation", annotation);
if (declaredAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = declaredAnnotations.get(annotation);
if (values != null) {
return Optional.of(new AnnotationValue<>(annotation, values, AnnotationMetadataSupport.getDefaultValues(annotation)));
} else if (declaredStereotypes != null) {
values = declaredStereotypes.get(annotation);
if (values != null) {
return Optional.of(new AnnotationValue<>(annotation, values, AnnotationMetadataSupport.getDefaultValues(annotation)));
}
}
}
return Optional.empty();
}
@Override
public @NonNull
<T> OptionalValues<T> getValues(@NonNull String annotation, @NonNull Class<T> valueType) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("valueType", valueType);
if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = allAnnotations.get(annotation);
if (values != null) {
return OptionalValues.of(valueType, values);
} else if (allStereotypes != null) {
values = allStereotypes.get(annotation);
if (values != null) {
return OptionalValues.of(valueType, values);
}
}
}
return OptionalValues.empty();
}
@Override
public @NonNull
<T> Optional<T> getDefaultValue(@NonNull String annotation, @NonNull String member, @NonNull Argument<T> requiredType) {
ArgumentUtils.requireNonNull("annotation", annotation);
ArgumentUtils.requireNonNull("member", member);
ArgumentUtils.requireNonNull("requiredType", requiredType);
Map<String, Object> defaultValues = AnnotationMetadataSupport.getDefaultValues(annotation);
if (defaultValues.containsKey(member)) {
return ConversionService.SHARED.convert(defaultValues.get(member), requiredType);
}
return Optional.empty();
}
@Override
public DefaultAnnotationMetadata clone() {
return new DefaultAnnotationMetadata(
declaredAnnotations != null ? new HashMap<>(declaredAnnotations) : null,
declaredStereotypes != null ? new HashMap<>(declaredStereotypes) : null,
allStereotypes != null ? new HashMap<>(allStereotypes) : null,
allAnnotations != null ? new HashMap<>(allAnnotations) : null,
annotationsByStereotype != null ? new HashMap<>(annotationsByStereotype) : null
);
}
@SuppressWarnings("WeakerAccess")
protected final void addAnnotation(String annotation, Map<CharSequence, Object> values) {
addAnnotation(annotation, values, RetentionPolicy.RUNTIME);
}
@SuppressWarnings("WeakerAccess")
protected final void addAnnotation(String annotation, Map<CharSequence, Object> values, RetentionPolicy retentionPolicy) {
if (annotation != null) {
String repeatedName = getRepeatedName(annotation);
Object v = values.get(AnnotationMetadata.VALUE_MEMBER);
if (v instanceof io.micronaut.core.annotation.AnnotationValue[]) {
io.micronaut.core.annotation.AnnotationValue[] avs = (io.micronaut.core.annotation.AnnotationValue[]) v;
for (io.micronaut.core.annotation.AnnotationValue av : avs) {
addRepeatable(annotation, av);
}
} else if (v instanceof Iterable && repeatedName != null) {
Iterable i = (Iterable) v;
for (Object o : i) {
if (o instanceof io.micronaut.core.annotation.AnnotationValue) {
addRepeatable(annotation, ((io.micronaut.core.annotation.AnnotationValue) o));
}
}
} else {
Map<String, Map<CharSequence, Object>> allAnnotations = getAllAnnotations();
addAnnotation(annotation, values, null, allAnnotations, false, retentionPolicy);
}
}
}
protected final void addDefaultAnnotationValues(String annotation, Map<CharSequence, Object> values) {
if (annotation != null) {
Map<String, Map<CharSequence, Object>> annotationDefaults = this.annotationDefaultValues;
if (annotationDefaults == null) {
this.annotationDefaultValues = new HashMap<>();
annotationDefaults = this.annotationDefaultValues;
}
putValues(annotation, values, annotationDefaults);
}
}
@SuppressWarnings("unused")
@Internal
@UsedByGeneratedCode
public static boolean areAnnotationDefaultsRegistered(String annotation) {
return AnnotationMetadataSupport.hasDefaultValues(annotation);
}
@SuppressWarnings("unused")
@Internal
@UsedByGeneratedCode
public static void registerAnnotationDefaults(String annotation, Map<String, Object> defaultValues) {
AnnotationMetadataSupport.registerDefaultValues(annotation, defaultValues);
}
@SuppressWarnings("unused")
@Internal
@UsedByGeneratedCode
public static void registerAnnotationDefaults(AnnotationClassValue<?> annotation, Map<String, Object> defaultValues) {
AnnotationMetadataSupport.registerDefaultValues(annotation, defaultValues);
}
@SuppressWarnings("unused")
@Internal
@UsedByGeneratedCode
public static void registerAnnotationType(AnnotationClassValue<?> annotation) {
AnnotationMetadataSupport.registerAnnotationType(annotation);
}
protected final void addRepeatable(String annotationName, io.micronaut.core.annotation.AnnotationValue annotationValue) {
addRepeatable(annotationName, annotationValue, annotationValue.getRetentionPolicy());
}
protected final void addRepeatable(String annotationName, io.micronaut.core.annotation.AnnotationValue annotationValue, RetentionPolicy retentionPolicy) {
if (StringUtils.isNotEmpty(annotationName) && annotationValue != null) {
Map<String, Map<CharSequence, Object>> allAnnotations = getAllAnnotations();
addRepeatableInternal(annotationName, annotationValue, allAnnotations, retentionPolicy);
}
}
protected void addRepeatableStereotype(List<String> parents, String stereotype, io.micronaut.core.annotation.AnnotationValue annotationValue) {
Map<String, Map<CharSequence, Object>> allStereotypes = getAllStereotypes();
List<String> annotationList = getAnnotationsByStereotypeInternal(stereotype);
for (String parentAnnotation : parents) {
if (!annotationList.contains(parentAnnotation)) {
annotationList.add(parentAnnotation);
}
}
addRepeatableInternal(stereotype, annotationValue, allStereotypes, RetentionPolicy.RUNTIME);
}
protected void addDeclaredRepeatableStereotype(List<String> parents, String stereotype, io.micronaut.core.annotation.AnnotationValue annotationValue) {
Map<String, Map<CharSequence, Object>> declaredStereotypes = getDeclaredStereotypesInternal();
List<String> annotationList = getAnnotationsByStereotypeInternal(stereotype);
for (String parentAnnotation : parents) {
if (!annotationList.contains(parentAnnotation)) {
annotationList.add(parentAnnotation);
}
}
addRepeatableInternal(stereotype, annotationValue, declaredStereotypes, RetentionPolicy.RUNTIME);
addRepeatableInternal(stereotype, annotationValue, getAllStereotypes(), RetentionPolicy.RUNTIME);
}
protected final void addDeclaredRepeatable(String annotationName, io.micronaut.core.annotation.AnnotationValue annotationValue) {
addDeclaredRepeatable(annotationName, annotationValue, annotationValue.getRetentionPolicy());
}
protected final void addDeclaredRepeatable(String annotationName, io.micronaut.core.annotation.AnnotationValue annotationValue, RetentionPolicy retentionPolicy) {
if (StringUtils.isNotEmpty(annotationName) && annotationValue != null) {
Map<String, Map<CharSequence, Object>> allAnnotations = getDeclaredAnnotationsInternal();
addRepeatableInternal(annotationName, annotationValue, allAnnotations, retentionPolicy);
addRepeatable(annotationName, annotationValue);
}
}
@SuppressWarnings("WeakerAccess")
protected final void addStereotype(List<String> parentAnnotations, String stereotype, Map<CharSequence, Object> values) {
addStereotype(parentAnnotations, stereotype, values, RetentionPolicy.RUNTIME);
}
@SuppressWarnings("WeakerAccess")
protected final void addStereotype(List<String> parentAnnotations, String stereotype, Map<CharSequence, Object> values, RetentionPolicy retentionPolicy) {
if (stereotype != null) {
String repeatedName = getRepeatedName(stereotype);
if (repeatedName != null) {
Object v = values.get(AnnotationMetadata.VALUE_MEMBER);
if (v instanceof io.micronaut.core.annotation.AnnotationValue[]) {
io.micronaut.core.annotation.AnnotationValue[] avs = (io.micronaut.core.annotation.AnnotationValue[]) v;
for (io.micronaut.core.annotation.AnnotationValue av : avs) {
addRepeatableStereotype(parentAnnotations, stereotype, av);
}
} else if (v instanceof Iterable) {
Iterable i = (Iterable) v;
for (Object o : i) {
if (o instanceof io.micronaut.core.annotation.AnnotationValue) {
addRepeatableStereotype(parentAnnotations, stereotype, (io.micronaut.core.annotation.AnnotationValue) o);
}
}
}
} else {
Map<String, Map<CharSequence, Object>> allStereotypes = getAllStereotypes();
List<String> annotationList = getAnnotationsByStereotypeInternal(stereotype);
for (String parentAnnotation : parentAnnotations) {
if (!annotationList.contains(parentAnnotation)) {
annotationList.add(parentAnnotation);
}
}
addAnnotation(
stereotype,
values,
null,
allStereotypes,
false,
retentionPolicy
);
}
}
}
@SuppressWarnings("WeakerAccess")
protected final void addDeclaredStereotype(List<String> parentAnnotations, String stereotype, Map<CharSequence, Object> values) {
addDeclaredStereotype(parentAnnotations, stereotype, values, RetentionPolicy.RUNTIME);
}
@SuppressWarnings("WeakerAccess")
protected final void addDeclaredStereotype(List<String> parentAnnotations, String stereotype, Map<CharSequence, Object> values, RetentionPolicy retentionPolicy) {
if (stereotype != null) {
String repeatedName = getRepeatedName(stereotype);
if (repeatedName != null) {
Object v = values.get(AnnotationMetadata.VALUE_MEMBER);
if (v instanceof io.micronaut.core.annotation.AnnotationValue[]) {
io.micronaut.core.annotation.AnnotationValue[] avs = (io.micronaut.core.annotation.AnnotationValue[]) v;
for (io.micronaut.core.annotation.AnnotationValue av : avs) {
addDeclaredRepeatableStereotype(parentAnnotations, stereotype, av);
}
} else if (v instanceof Iterable) {
Iterable i = (Iterable) v;
for (Object o : i) {
if (o instanceof io.micronaut.core.annotation.AnnotationValue) {
addDeclaredRepeatableStereotype(parentAnnotations, stereotype, (io.micronaut.core.annotation.AnnotationValue) o);
}
}
}
} else {
Map<String, Map<CharSequence, Object>> declaredStereotypes = getDeclaredStereotypesInternal();
Map<String, Map<CharSequence, Object>> allStereotypes = getAllStereotypes();
List<String> annotationList = getAnnotationsByStereotypeInternal(stereotype);
for (String parentAnnotation : parentAnnotations) {
if (!annotationList.contains(parentAnnotation)) {
annotationList.add(parentAnnotation);
}
}
addAnnotation(
stereotype,
values,
declaredStereotypes,
allStereotypes,
true,
retentionPolicy
);
}
}
}
protected void addDeclaredAnnotation(String annotation, Map<CharSequence, Object> values) {
addDeclaredAnnotation(annotation, values, RetentionPolicy.RUNTIME);
}
protected void addDeclaredAnnotation(String annotation, Map<CharSequence, Object> values, RetentionPolicy retentionPolicy) {
if (annotation != null) {
String repeatedName = getRepeatedName(annotation);
if (repeatedName != null) {
Object v = values.get(AnnotationMetadata.VALUE_MEMBER);
if (v instanceof io.micronaut.core.annotation.AnnotationValue[]) {
io.micronaut.core.annotation.AnnotationValue[] avs = (io.micronaut.core.annotation.AnnotationValue[]) v;
for (io.micronaut.core.annotation.AnnotationValue av : avs) {
addDeclaredRepeatable(annotation, av);
}
} else if (v instanceof Iterable) {
Iterable i = (Iterable) v;
for (Object o : i) {
if (o instanceof io.micronaut.core.annotation.AnnotationValue) {
addDeclaredRepeatable(annotation, ((io.micronaut.core.annotation.AnnotationValue) o));
}
}
}
} else {
Map<String, Map<CharSequence, Object>> declaredAnnotations = getDeclaredAnnotationsInternal();
Map<String, Map<CharSequence, Object>> allAnnotations = getAllAnnotations();
addAnnotation(annotation, values, declaredAnnotations, allAnnotations, true, retentionPolicy);
}
}
}
@SuppressWarnings("unused")
@Internal
void dump() {
System.out.println("declaredAnnotations = " + declaredAnnotations);
System.out.println("declaredStereotypes = " + declaredStereotypes);
System.out.println("allAnnotations = " + allAnnotations);
System.out.println("allStereotypes = " + allStereotypes);
System.out.println("annotationsByStereotype = " + annotationsByStereotype);
}
private <T extends Annotation> List<io.micronaut.core.annotation.AnnotationValue<T>> resolveAnnotationValuesByType(Class<T> annotationType, Map<String, Map<CharSequence, Object>> sourceAnnotations, Map<String, Map<CharSequence, Object>> sourceStereotypes) {
Repeatable repeatable = annotationType.getAnnotation(Repeatable.class);
if (repeatable != null) {
Class<? extends Annotation> repeatableType = repeatable.value();
if (hasStereotype(repeatableType)) {
List<io.micronaut.core.annotation.AnnotationValue<T>> results = new ArrayList<>();
if (sourceAnnotations != null) {
Map<CharSequence, Object> values = sourceAnnotations.get(repeatableType.getName());
addAnnotationValuesFromData(results, values);
}
if (sourceStereotypes != null) {
Map<CharSequence, Object> values = sourceStereotypes.get(repeatableType.getName());
addAnnotationValuesFromData(results, values);
}
return results;
}
}
return null;
}
private void addAnnotation(String annotation,
Map<CharSequence, Object> values,
Map<String, Map<CharSequence, Object>> declaredAnnotations,
Map<String, Map<CharSequence, Object>> allAnnotations,
boolean isDeclared,
RetentionPolicy retentionPolicy) {
if (isDeclared && declaredAnnotations != null) {
putValues(annotation, values, declaredAnnotations);
}
putValues(annotation, values, allAnnotations);
if (retentionPolicy == RetentionPolicy.SOURCE) {
addSourceRetentionAnnotation(annotation);
}
}
private void addSourceRetentionAnnotation(String annotation) {
if (sourceRetentionAnnotations == null) {
sourceRetentionAnnotations = new HashSet<>(5);
}
sourceRetentionAnnotations.add(annotation);
}
private void putValues(String annotation, Map<CharSequence, Object> values, Map<String, Map<CharSequence, Object>> currentAnnotationValues) {
Map<CharSequence, Object> existing = currentAnnotationValues.get(annotation);
boolean hasValues = CollectionUtils.isNotEmpty(values);
if (existing != null && hasValues) {
if (existing.isEmpty()) {
existing = new LinkedHashMap<>();
currentAnnotationValues.put(annotation, existing);
}
for (CharSequence key : values.keySet()) {
if (!existing.containsKey(key)) {
existing.put(key, values.get(key));
}
}
} else {
if (!hasValues) {
existing = existing == null ? Collections.emptyMap() : existing;
} else {
existing = new LinkedHashMap<>(values.size());
existing.putAll(values);
}
currentAnnotationValues.put(annotation, existing);
}
}
@SuppressWarnings("MagicNumber")
private Map<String, Map<CharSequence, Object>> getAllStereotypes() {
Map<String, Map<CharSequence, Object>> stereotypes = this.allStereotypes;
if (stereotypes == null) {
stereotypes = new HashMap<>(3);
this.allStereotypes = stereotypes;
}
return stereotypes;
}
@SuppressWarnings("MagicNumber")
private Map<String, Map<CharSequence, Object>> getDeclaredStereotypesInternal() {
Map<String, Map<CharSequence, Object>> stereotypes = this.declaredStereotypes;
if (stereotypes == null) {
stereotypes = new HashMap<>(3);
this.declaredStereotypes = stereotypes;
}
return stereotypes;
}
@SuppressWarnings("MagicNumber")
private Map<String, Map<CharSequence, Object>> getAllAnnotations() {
Map<String, Map<CharSequence, Object>> annotations = this.allAnnotations;
if (annotations == null) {
annotations = new HashMap<>(3);
this.allAnnotations = annotations;
}
return annotations;
}
@SuppressWarnings("MagicNumber")
private Map<String, Map<CharSequence, Object>> getDeclaredAnnotationsInternal() {
Map<String, Map<CharSequence, Object>> annotations = this.declaredAnnotations;
if (annotations == null) {
annotations = new HashMap<>(3);
this.declaredAnnotations = annotations;
}
return annotations;
}
private List<String> getAnnotationsByStereotypeInternal(String stereotype) {
return getAnnotationsByStereotypeInternal().computeIfAbsent(stereotype, s -> new ArrayList<>());
}
private String getRepeatedName(String annotation) {
if (repeated != null) {
return repeated.get(annotation);
}
return null;
}
@SuppressWarnings("MagicNumber")
private Map<String, List<String>> getAnnotationsByStereotypeInternal() {
Map<String, List<String>> annotations = this.annotationsByStereotype;
if (annotations == null) {
annotations = new HashMap<>(3);
this.annotationsByStereotype = annotations;
}
return annotations;
}
private @Nullable
Object getRawSingleValue(@NonNull String annotation, @NonNull String member, @Nullable Function<Object, Object> valueMapper) {
Object rawValue = getRawValue(annotation, member);
if (rawValue != null) {
if (rawValue.getClass().isArray()) {
int len = Array.getLength(rawValue);
if (len > 0) {
rawValue = Array.get(rawValue, 0);
}
} else if (rawValue instanceof Iterable) {
Iterator i = ((Iterable) rawValue).iterator();
if (i.hasNext()) {
rawValue = i.next();
}
}
}
if (valueMapper != null && rawValue instanceof CharSequence) {
return valueMapper.apply(rawValue);
} else {
return rawValue;
}
}
@Nullable
private Object getRawValue(@NonNull String annotation, @NonNull String member) {
Object rawValue = null;
if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
Map<CharSequence, Object> values = allAnnotations.get(annotation);
if (values != null) {
rawValue = values.get(member);
} else if (allStereotypes != null) {
values = allStereotypes.get(annotation);
if (values != null) {
rawValue = values.get(member);
}
}
}
return rawValue;
}
private void addRepeatableInternal(
String annotationName,
io.micronaut.core.annotation.AnnotationValue annotationValue,
Map<String, Map<CharSequence, Object>> allAnnotations,
RetentionPolicy retentionPolicy) {
addRepeatableInternal(annotationName, AnnotationMetadata.VALUE_MEMBER, annotationValue, allAnnotations, retentionPolicy);
}
private void addRepeatableInternal(
String annotationName,
String member,
io.micronaut.core.annotation.AnnotationValue annotationValue,
Map<String, Map<CharSequence, Object>> allAnnotations,
RetentionPolicy retentionPolicy) {
if (repeated == null) {
repeated = new HashMap<>(2);
}
repeated.put(annotationName, annotationValue.getAnnotationName());
if (retentionPolicy == RetentionPolicy.SOURCE) {
addSourceRetentionAnnotation(annotationName);
}
Map<CharSequence, Object> values = allAnnotations.computeIfAbsent(annotationName, s -> new HashMap<>());
Object v = values.get(member);
if (v != null) {
if (v.getClass().isArray()) {
Object[] array = (Object[]) v;
Set newValues = new LinkedHashSet(array.length + 1);
newValues.addAll(Arrays.asList(array));
newValues.add(annotationValue);
values.put(member, newValues);
} else if (v instanceof Collection) {
((Collection) v).add(annotationValue);
}
} else {
Set<Object> newValues = new LinkedHashSet<>(2);
newValues.add(annotationValue);
values.put(member, newValues);
}
}
@Internal
public static AnnotationMetadata mutateMember(
AnnotationMetadata annotationMetadata,
String annotationName,
String member,
Object value) {
return mutateMember(annotationMetadata, annotationName, Collections.singletonMap(member, value));
}
@Internal
public static void contributeDefaults(AnnotationMetadata target, AnnotationMetadata source) {
if (source instanceof AnnotationMetadataHierarchy) {
source = ((AnnotationMetadataHierarchy) source).getDeclaredMetadata();
}
if (target instanceof DefaultAnnotationMetadata && source instanceof DefaultAnnotationMetadata) {
final Map<String, Map<CharSequence, Object>> existingDefaults = ((DefaultAnnotationMetadata) target).annotationDefaultValues;
if (existingDefaults != null) {
final Map<String, Map<CharSequence, Object>> additionalDefaults = ((DefaultAnnotationMetadata) source).annotationDefaultValues;
if (additionalDefaults != null) {
existingDefaults.putAll(
additionalDefaults
);
}
} else {
final Map<String, Map<CharSequence, Object>> additionalDefaults = ((DefaultAnnotationMetadata) source).annotationDefaultValues;
if (additionalDefaults != null) {
additionalDefaults.forEach(((DefaultAnnotationMetadata) target)::addDefaultAnnotationValues);
}
}
}
}
@Internal
public static AnnotationMetadata mutateMember(
AnnotationMetadata annotationMetadata,
String annotationName,
Map<CharSequence, Object> members) {
if (StringUtils.isEmpty(annotationName)) {
throw new IllegalArgumentException("Argument [annotationName] cannot be blank");
}
if (!members.isEmpty()) {
for (Map.Entry<CharSequence, Object> entry : members.entrySet()) {
if (StringUtils.isEmpty(entry.getKey())) {
throw new IllegalArgumentException("Argument [members] cannot have a blank key");
}
if (entry.getValue() == null) {
throw new IllegalArgumentException("Argument [members] cannot have a null value. Key [" + entry.getKey() + "]");
}
}
}
if (!(annotationMetadata instanceof DefaultAnnotationMetadata)) {
return new DefaultAnnotationMetadata() {{
addDeclaredAnnotation(annotationName, members);
}};
} else {
DefaultAnnotationMetadata defaultMetadata = (DefaultAnnotationMetadata) annotationMetadata;
defaultMetadata = defaultMetadata.clone();
defaultMetadata
.addDeclaredAnnotation(annotationName, members);
return defaultMetadata;
}
}
}