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

io.micronaut.inject.annotation.AnnotationMetadataHierarchy Maven / Gradle / Ivy

There is a newer version: 4.7.5
Show newest version
/*
 * Copyright 2017-2020 original authors
 *
 * 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
 *
 * https://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 io.micronaut.inject.annotation;

import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationUtil;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.ArrayUtils;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.core.value.OptionalValues;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * Used to represent an annotation metadata hierarchy. The first {@link AnnotationMetadata} instance passed
 * to the constructor represents the annotation metadata that is declared, hence methods like {@link #hasDeclaredAnnotation(String)} will return true for the last annotation metadata passed in the hierarchy.
 *
 * 

This class is used to internally optimize memory usage and compilation time for classes that declare * AOP advice at the type level and where the classes methods typically don't include any annotations and therefore * would be wasteful to generate additional annotation metadata classes.

* * @author graemerocher * @since 1.3.0 */ public final class AnnotationMetadataHierarchy implements AnnotationMetadata, EnvironmentAnnotationMetadata, Iterable { /** * Constant to represent an empty hierarchy. */ public static final AnnotationMetadata[] EMPTY_HIERARCHY = {AnnotationMetadata.EMPTY_METADATA, AnnotationMetadata.EMPTY_METADATA}; private final AnnotationMetadata[] hierarchy; private final boolean delegateDeclaredToAllElements; /** * Default constructor. * * @param hierarchy The annotation hierarchy */ public AnnotationMetadataHierarchy(AnnotationMetadata... hierarchy) { this(false, hierarchy); } /** * Default constructor. * * @param hierarchy The annotation hierarchy * @param delegateDeclaredToAllElements The delegate declared to all elements */ @Internal public AnnotationMetadataHierarchy(boolean delegateDeclaredToAllElements, AnnotationMetadata... hierarchy) { this.delegateDeclaredToAllElements = delegateDeclaredToAllElements; if (ArrayUtils.isNotEmpty(hierarchy)) { ArrayUtils.reverse(hierarchy); this.hierarchy = hierarchy; } else { this.hierarchy = EMPTY_HIERARCHY; } } /** * Copy constructor. * * @param existing Existing * @param newChild new child */ private AnnotationMetadataHierarchy(AnnotationMetadata[] existing, AnnotationMetadata newChild) { hierarchy = new AnnotationMetadata[existing.length]; System.arraycopy(existing, 0, hierarchy, 0, existing.length); hierarchy[0] = newChild; delegateDeclaredToAllElements = false; } @Override public boolean hasPropertyExpressions() { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasPropertyExpressions()) { return true; } } return false; } @Override public boolean hasEvaluatedExpressions() { for (AnnotationMetadata annotationMetadata: hierarchy) { if (annotationMetadata.hasEvaluatedExpressions()) { return true; } } return false; } @Override public Optional> getAnnotationType(@NonNull String name) { for (AnnotationMetadata metadata : hierarchy) { Optional> annotationType = metadata.getAnnotationType(name); if (annotationType.isPresent()) { return annotationType; } } return Optional.empty(); } @Override public Optional> getAnnotationType(@NonNull String name, @NonNull ClassLoader classLoader) { for (AnnotationMetadata metadata : hierarchy) { Optional> annotationType = metadata.getAnnotationType(name, classLoader); if (annotationType.isPresent()) { return annotationType; } } return Optional.empty(); } /** * @return The metadata that is actually declared in the element */ @NonNull @Override public AnnotationMetadata getDeclaredMetadata() { return hierarchy[0]; } /** * @return The metadata that is actually declared in the element */ @NonNull public AnnotationMetadata getRootMetadata() { return hierarchy[hierarchy.length - 1]; } /** * Create a new hierarchy instance from this metadata using this metadata's parents. * * @param child The child annotation metadata * @return A new sibling */ @NonNull public AnnotationMetadata createSibling(@NonNull AnnotationMetadata child) { if (hierarchy.length > 1) { return new AnnotationMetadataHierarchy(hierarchy, child); } else { return child; } } @Nullable @Override public T synthesize(@NonNull Class annotationClass, @NonNull String sourceAnnotation) { for (AnnotationMetadata annotationMetadata : hierarchy) { final T a = annotationMetadata.synthesize(annotationClass, sourceAnnotation); if (a != null) { return a; } } return null; } @Override public Annotation[] synthesizeAll() { return Stream.of(hierarchy).flatMap(am -> Arrays.stream(am.synthesizeAll())).toArray(Annotation[]::new); } @Override public Annotation[] synthesizeDeclared() { return Stream.of(hierarchy).flatMap(am -> Arrays.stream(am.synthesizeDeclared())).toArray(Annotation[]::new); } @Override @SuppressWarnings("unchecked") public T[] synthesizeAnnotationsByType(Class annotationClass) { if (annotationClass == null) { return (T[]) AnnotationUtil.ZERO_ANNOTATIONS; } return Stream.of(hierarchy) .flatMap(am -> am.getAnnotationValuesByType(annotationClass).stream()) .distinct() .map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, entries)) .toArray(value -> (T[]) Array.newInstance(annotationClass, value)); } @SuppressWarnings("unchecked") public T[] synthesizeDeclaredAnnotationsByType(Class annotationClass) { if (annotationClass == null) { return (T[]) AnnotationUtil.ZERO_ANNOTATIONS; } return Stream.of(hierarchy) .flatMap(am -> am.getAnnotationValuesByType(annotationClass).stream()) .distinct() .map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, entries)) .toArray(value -> (T[]) Array.newInstance(annotationClass, value)); } @Nullable @Override public T synthesizeDeclared(@NonNull Class annotationClass, @NonNull String sourceAnnotation) { return hierarchy[0].synthesize(annotationClass, sourceAnnotation); } @Nullable @Override public T synthesize(@NonNull Class annotationClass) { for (AnnotationMetadata annotationMetadata : hierarchy) { final T a = annotationMetadata.synthesize(annotationClass); if (a != null) { return a; } } return null; } @Nullable @Override public T synthesizeDeclared(@NonNull Class annotationClass) { if (delegateDeclaredToAllElements) { return merge().synthesizeDeclared(annotationClass); } return hierarchy[0].synthesize(annotationClass); } @NonNull @Override public Optional> findAnnotation(@NonNull String annotation) { AnnotationValue existing = null; for (AnnotationMetadata annotationMetadata : hierarchy) { existing = mergeValue(annotation, existing, annotationMetadata.getAnnotation(annotation)); } return Optional.ofNullable(existing); } @Nullable private AnnotationValue mergeValue(@NonNull String annotation, @Nullable AnnotationValue existingValue, @Nullable AnnotationValue newValue) { if (newValue == null) { return existingValue; } if (existingValue == null) { return newValue; } final Map values = newValue.getValues(); final Map existing = existingValue.getValues(); Map newValues = CollectionUtils.newLinkedHashMap(values.size() + existing.size()); newValues.putAll(existing); for (Map.Entry entry : values.entrySet()) { newValues.putIfAbsent(entry.getKey(), entry.getValue()); } Map newDefaults = newValue.getDefaultValues(); Map existingDefaults = existingValue.getDefaultValues(); return new AnnotationValue<>( annotation, newValues, existingDefaults != null ? existingDefaults : newDefaults ); } @NonNull @Override public Optional> findDeclaredAnnotation(@NonNull String annotation) { if (delegateDeclaredToAllElements) { AnnotationValue existing = null; for (AnnotationMetadata annotationMetadata : hierarchy) { existing = mergeValue(annotation, existing, annotationMetadata.getDeclaredAnnotation(annotation)); } return Optional.ofNullable(existing); } return hierarchy[0].findDeclaredAnnotation(annotation); } @NonNull @Override public OptionalDouble doubleValue(@NonNull Class annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalDouble o = annotationMetadata.doubleValue(annotation, member); if (o.isPresent()) { return o; } } return OptionalDouble.empty(); } @NonNull @Override public String[] stringValues(@NonNull Class annotation, @NonNull String member) { return stringValues(annotation.getName(), member); } @NonNull @Override public String[] stringValues(@NonNull String annotation, @NonNull String member) { String[] values = hierarchy[0].stringValues(annotation, member); for (int i = 1; i < hierarchy.length; i++) { AnnotationMetadata annotationMetadata = hierarchy[i]; final String[] moreValues = annotationMetadata.stringValues(annotation, member); if (ArrayUtils.isNotEmpty(moreValues)) { values = ArrayUtils.concat(values, moreValues); } } return values; } @Override public Optional booleanValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o = annotationMetadata.booleanValue(annotation, member); if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public boolean isTrue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata am : hierarchy) { if (am.isTrue(annotation, member)) { return true; } } return false; } @Override public OptionalLong longValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalLong o = annotationMetadata.longValue(annotation, member); if (o.isPresent()) { return o; } } return OptionalLong.empty(); } @Override public Optional stringValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o = annotationMetadata.stringValue(annotation, member); if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public OptionalInt intValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalInt o = annotationMetadata.intValue(annotation, member); if (o.isPresent()) { return o; } } return OptionalInt.empty(); } @NonNull @Override public OptionalDouble doubleValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalDouble o = annotationMetadata.doubleValue(annotation, member); if (o.isPresent()) { return o; } } return OptionalDouble.empty(); } @Override public > Optional enumValue(@NonNull Class annotation, @NonNull String member, Class enumType) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o = annotationMetadata.enumValue(annotation, member, enumType); if (o.isPresent()) { return o; } } return Optional.empty(); } @SuppressWarnings("unchecked") @NonNull @Override public Class[] classValues(@NonNull String annotation, @NonNull String member) { List> list = new ArrayList<>(); for (AnnotationMetadata am : hierarchy) { list.addAll(Arrays.asList(am.classValues(annotation, member))); } return list.toArray(new Class[0]); } @Override public Optional classValue(@NonNull String annotation, @NonNull String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o = annotationMetadata.classValue(annotation, member); if (o.isPresent()) { return o; } } return Optional.empty(); } @NonNull @Override public List getAnnotationNamesByStereotype(@Nullable String stereotype) { Set list = new LinkedHashSet<>(); for (AnnotationMetadata am : hierarchy) { list.addAll(am.getAnnotationNamesByStereotype(stereotype)); } return new ArrayList<>(list); } @Override public List> getAnnotationValuesByStereotype(String stereotype) { Set> list = new LinkedHashSet<>(); for (AnnotationMetadata am : hierarchy) { list.addAll(am.getAnnotationValuesByStereotype(stereotype)); } return new ArrayList<>(list); } @NonNull @Override public Set getDeclaredAnnotationNames() { if (delegateDeclaredToAllElements) { Set set = new HashSet<>(); for (AnnotationMetadata am : hierarchy) { set.addAll(am.getDeclaredAnnotationNames()); } return set; } return hierarchy[0].getDeclaredAnnotationNames(); } @NonNull @Override public Set getAnnotationNames() { Set set = new HashSet<>(); for (AnnotationMetadata am : hierarchy) { set.addAll(am.getAnnotationNames()); } return set; } @NonNull @Override public OptionalValues getValues(@NonNull String annotation, @NonNull Class valueType) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalValues values = annotationMetadata.getValues(annotation, valueType); if (!values.isEmpty()) { return values; } } return OptionalValues.empty(); } @Override public Optional getDefaultValue(@NonNull String annotation, @NonNull String member, @NonNull Argument requiredType) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional defaultValue = annotationMetadata.getDefaultValue(annotation, member, requiredType); if (defaultValue.isPresent()) { return defaultValue; } } return Optional.empty(); } @NonNull @Override public List> getAnnotationValuesByType(@NonNull Class annotationType) { List> list = new ArrayList<>(10); Set> uniqueValues = new HashSet<>(10); for (AnnotationMetadata am : hierarchy) { for (AnnotationValue tAnnotationValue : am.getAnnotationValuesByType(annotationType)) { if (uniqueValues.add(tAnnotationValue)) { list.add(tAnnotationValue); } } } return list; } @Override public List> getAnnotationValuesByName(String annotationType) { if (annotationType == null) { return Collections.emptyList(); } return mergeAnnotationValues(annotationType, AnnotationMetadata::getAnnotationValuesByName); } @NonNull private List> mergeAnnotationValues(V annotationType, BiFunction>> fn) { List> list = new ArrayList<>(10); Set> uniqueValues = new HashSet<>(10); for (AnnotationMetadata am : hierarchy) { for (AnnotationValue tAnnotationValue : fn.apply(am, annotationType)) { if (uniqueValues.add(tAnnotationValue)) { list.add(tAnnotationValue); } } } return Collections.unmodifiableList(list); } @NonNull @Override public List> getDeclaredAnnotationValuesByType(@NonNull Class annotationType) { if (delegateDeclaredToAllElements) { return mergeAnnotationValues(annotationType, AnnotationMetadata::getDeclaredAnnotationValuesByType); } return hierarchy[0].getDeclaredAnnotationValuesByType(annotationType); } @Override public List> getDeclaredAnnotationValuesByName(String annotationType) { if (delegateDeclaredToAllElements) { return mergeAnnotationValues(annotationType, AnnotationMetadata::getDeclaredAnnotationValuesByName); } return hierarchy[0].getDeclaredAnnotationValuesByName(annotationType); } @Override public boolean hasDeclaredAnnotation(@Nullable String annotation) { if (delegateDeclaredToAllElements) { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasDeclaredAnnotation(annotation)) { return true; } } return false; } return hierarchy[0].hasDeclaredAnnotation(annotation); } @Override public boolean hasAnnotation(@Nullable String annotation) { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasAnnotation(annotation)) { return true; } } return false; } @Override public boolean hasStereotype(@Nullable String annotation) { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasStereotype(annotation)) { return true; } } return false; } @Override public boolean hasDeclaredStereotype(@Nullable String annotation) { if (delegateDeclaredToAllElements) { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasDeclaredStereotype(annotation)) { return true; } } return false; } return hierarchy[0].hasDeclaredStereotype(annotation); } @Override public > Optional enumValue(String annotation, String member, Class enumType) { return enumValue(annotation, member, enumType, null); } @Override public > E[] enumValues(String annotation, String member, Class enumType) { return enumValues(annotation, member, enumType, null); } @Override public OptionalInt intValue(Class annotation, String member) { return intValue(annotation, member, null); } @Override public boolean isFalse(Class annotation, String member) { return !booleanValue(annotation, member, null).orElse(false); } @NonNull @Override public Map getDefaultValues(@NonNull String annotation) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Map defaultValues = annotationMetadata.getDefaultValues(annotation); if (!defaultValues.isEmpty()) { return defaultValues; } } return Collections.emptyMap(); } @Override public > Optional enumValue(@NonNull Class annotation, @NonNull String member, Class enumType, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.enumValue(annotation, member, enumType, valueMapper); } else { o = annotationMetadata.enumValue(annotation, member, enumType); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public > Optional enumValue(@NonNull String annotation, @NonNull String member, Class enumType, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.enumValue(annotation, member, enumType, valueMapper); } else { o = annotationMetadata.enumValue(annotation, member, enumType); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public > E[] enumValues(@NonNull Class annotation, @NonNull String member, Class enumType, @Nullable Function valueMapper) { E[] values = hierarchy[0].enumValues(annotation, member, enumType); for (int i = 1; i < hierarchy.length; i++) { AnnotationMetadata annotationMetadata = hierarchy[i]; final E[] moreValues = annotationMetadata.enumValues(annotation, member, enumType); if (ArrayUtils.isNotEmpty(moreValues)) { values = ArrayUtils.concat(values, moreValues); } } return values; } @Override public > E[] enumValues(@NonNull String annotation, @NonNull String member, Class enumType, @Nullable Function valueMapper) { E[] values = hierarchy[0].enumValues(annotation, member, enumType); for (int i = 1; i < hierarchy.length; i++) { AnnotationMetadata annotationMetadata = hierarchy[i]; final E[] moreValues = annotationMetadata.enumValues(annotation, member, enumType); if (ArrayUtils.isNotEmpty(moreValues)) { values = ArrayUtils.concat(values, moreValues); } } return values; } @Override public Optional classValue(@NonNull Class annotation, @NonNull String member, Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.classValue(annotation, member, valueMapper); } else { o = annotationMetadata.classValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public Optional classValue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.classValue(annotation, member, valueMapper); } else { o = annotationMetadata.classValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public OptionalInt intValue(@NonNull Class annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalInt o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.intValue(annotation, member, valueMapper); } else { o = annotationMetadata.intValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalInt.empty(); } @Override public Optional booleanValue(@NonNull Class annotation, @NonNull String member, Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.booleanValue(annotation, member, valueMapper); } else { o = annotationMetadata.booleanValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @NonNull @Override public Optional booleanValue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.booleanValue(annotation, member, valueMapper); } else { o = annotationMetadata.booleanValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public OptionalLong longValue(@NonNull Class annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalLong o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.longValue(annotation, member, valueMapper); } else { o = annotationMetadata.longValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalLong.empty(); } @NonNull @Override public OptionalLong longValue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalLong o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.longValue(annotation, member, valueMapper); } else { o = annotationMetadata.longValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalLong.empty(); } @NonNull @Override public OptionalInt intValue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalInt o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.intValue(annotation, member, valueMapper); } else { o = annotationMetadata.intValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalInt.empty(); } @Override public OptionalLong longValue(Class annotation, String member) { return longValue(annotation, member, null); } @Override public > E[] enumValues(Class annotation, String member, Class enumType) { return enumValues(annotation, member, enumType, null); } @Override public Class[] classValues(Class annotation, String member) { List> list = new ArrayList<>(); for (AnnotationMetadata am : hierarchy) { list.addAll(Arrays.asList(am.classValues(annotation, member))); } return list.toArray(new Class[0]); } @Override public Optional classValue(Class annotation, String member) { return classValue(annotation, member, null); } @Override public Optional stringValue(Class annotation, String member) { return stringValue(annotation, member, null); } @Override public Optional booleanValue(Class annotation, String member) { return booleanValue(annotation, member, null); } @Override public boolean isTrue(Class annotation, String member) { return isTrue(annotation, member, null); } @Override public boolean isPresent(Class annotation, String member) { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.isPresent(annotation, member)) { return true; } } return false; } @Override public Optional stringValue(@NonNull Class annotation, @NonNull String member, Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.stringValue(annotation, member, valueMapper); } else { o = annotationMetadata.stringValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @NonNull @Override public String[] stringValues(@NonNull Class annotation, @NonNull String member, Function valueMapper) { List strings = new ArrayList<>(); for (AnnotationMetadata am : hierarchy) { if (am instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { strings.addAll(Arrays.asList(environmentAnnotationMetadata.stringValues(annotation, member, valueMapper))); } else { strings.addAll(Arrays.asList(am.stringValues(annotation, member))); } } return strings.toArray(new String[0]); } @Override public String[] stringValues(String annotation, String member, Function valueMapper) { List strings = new ArrayList<>(); for (AnnotationMetadata am : hierarchy) { if (am instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { strings.addAll(Arrays.asList(environmentAnnotationMetadata.stringValues(annotation, member, valueMapper))); } else { strings.addAll(Arrays.asList(am.stringValues(annotation, member))); } } return strings.toArray(new String[0]); } @NonNull @Override public Optional stringValue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.stringValue(annotation, member, valueMapper); } else { o = annotationMetadata.stringValue(annotation, member); } if (o.isPresent()) { return o; } } return Optional.empty(); } @Override public boolean isTrue(@NonNull Class annotation, @NonNull String member, Function valueMapper) { return booleanValue(annotation, member, valueMapper).orElse(false); } @Override public boolean isTrue(@NonNull String annotation, @NonNull String member, @Nullable Function valueMapper) { return booleanValue(annotation, member, valueMapper).orElse(false); } @Override public OptionalDouble doubleValue(@NonNull Class annotation, @NonNull String member, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalDouble o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.doubleValue(annotation, member, valueMapper); } else { o = annotationMetadata.doubleValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalDouble.empty(); } @NonNull @Override public OptionalDouble doubleValue(@NonNull String annotation, @NonNull String member, Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final OptionalDouble o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.doubleValue(annotation, member, valueMapper); } else { o = annotationMetadata.doubleValue(annotation, member); } if (o.isPresent()) { return o; } } return OptionalDouble.empty(); } @NonNull @Override public Optional getValue(@NonNull String annotation, @NonNull String member, @NonNull Argument requiredType, @Nullable Function valueMapper) { for (AnnotationMetadata annotationMetadata : hierarchy) { final Optional o; if (annotationMetadata instanceof EnvironmentAnnotationMetadata environmentAnnotationMetadata) { o = environmentAnnotationMetadata.getValue(annotation, member, requiredType, valueMapper); } else { o = annotationMetadata.getValue(annotation, member, requiredType); } if (o.isPresent()) { return o; } } return Optional.empty(); } @NonNull @Override public Iterator iterator() { return ArrayUtils.reverseIterator(hierarchy); } @Override public boolean isEmpty() { for (AnnotationMetadata metadata : hierarchy) { if (!metadata.isEmpty()) { return false; } } return true; } @Override public boolean isRepeatableAnnotation(Class annotation) { for (AnnotationMetadata metadata : hierarchy) { if (metadata.isRepeatableAnnotation(annotation)) { return true; } } return false; } @Override public boolean isRepeatableAnnotation(String annotation) { for (AnnotationMetadata metadata : hierarchy) { if (metadata.isRepeatableAnnotation(annotation)) { return true; } } return false; } @Override public Optional findRepeatableAnnotation(Class annotation) { for (AnnotationMetadata metadata : hierarchy) { Optional repeatable = metadata.findRepeatableAnnotation(annotation); if (repeatable.isPresent()) { return repeatable; } } return Optional.empty(); } @Override public Optional findRepeatableAnnotation(String annotation) { for (AnnotationMetadata metadata : hierarchy) { Optional repeatable = metadata.findRepeatableAnnotation(annotation); if (repeatable.isPresent()) { return repeatable; } } return Optional.empty(); } /** * Merges the hierarchy into one {@link MutableAnnotationMetadata}. * * @return merged metadata * @since 4.0.0 */ public MutableAnnotationMetadata merge() { MutableAnnotationMetadata newAnnotationMetadata = new MutableAnnotationMetadata(); for (AnnotationMetadata annotationMetadata : hierarchy) { annotationMetadata = annotationMetadata.getTargetAnnotationMetadata(); if (annotationMetadata.isEmpty()) { continue; } if (annotationMetadata instanceof AnnotationMetadataHierarchy annotationMetadataHierarchy) { newAnnotationMetadata.addAnnotationMetadata(annotationMetadataHierarchy.merge()); } else if (annotationMetadata instanceof MutableAnnotationMetadata mutableAnnotationMetadata) { newAnnotationMetadata.addAnnotationMetadata(mutableAnnotationMetadata); } else if (annotationMetadata instanceof DefaultAnnotationMetadata defaultAnnotationMetadata) { newAnnotationMetadata.addAnnotationMetadata(defaultAnnotationMetadata); } else { throw new IllegalStateException("Unknown instance of AnnotationMetadata: " + annotationMetadata.getClass()); } } return newAnnotationMetadata; } @Override public AnnotationMetadata copyAnnotationMetadata() { AnnotationMetadata[] copy = new AnnotationMetadata[hierarchy.length]; System.arraycopy(hierarchy, 0, copy, 0, hierarchy.length); ArrayUtils.reverse(copy); return new AnnotationMetadataHierarchy( delegateDeclaredToAllElements, Arrays.stream(copy).map(AnnotationMetadata::copyAnnotationMetadata).toArray(AnnotationMetadata[]::new) ); } /** * The size of the hierarchy. * @return The size * @since 4.0.0 */ public int size() { return hierarchy.length; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy