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.AnnotationValue;
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.value.OptionalValues;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
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; /** * Default constructor. * * @param hierarchy The annotation hierarchy */ public AnnotationMetadataHierarchy(AnnotationMetadata... hierarchy) { if (ArrayUtils.isNotEmpty(hierarchy)) { // place the first in the hierarchy first final int len = hierarchy.length; if (len > 1) { for (int i = 0; i < len / 2; i++) { AnnotationMetadata temp = hierarchy[i]; final int pos = len - i - 1; hierarchy[i] = hierarchy[pos]; hierarchy[pos] = temp; } } 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; } @Override public boolean hasPropertyExpressions() { for (AnnotationMetadata annotationMetadata : hierarchy) { if (annotationMetadata.hasPropertyExpressions()) { return true; } } return false; } @Override public Optional> getAnnotationType(@NonNull String name) { return getAnnotationType((metadata) -> metadata.getAnnotationType(name)); } @Override public Optional> getAnnotationType(@NonNull String name, @NonNull ClassLoader classLoader) { return getAnnotationType((metadata) -> metadata.getAnnotationType(name, classLoader)); } /** * @return The metadata that is actually declared in the element */ @NonNull 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) { 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) { return hierarchy[0].synthesize(annotationClass); } @NonNull @Override public Optional> findAnnotation(@NonNull String annotation) { AnnotationValue ann = null; for (AnnotationMetadata annotationMetadata : hierarchy) { final AnnotationValue av = annotationMetadata.getAnnotation(annotation); if (av != null) { if (ann == null) { ann = av; } else { final Map values = av.getValues(); final Map existing = ann.getValues(); Map newValues = new LinkedHashMap<>(values.size() + existing.size()); newValues.putAll(existing); for (Map.Entry entry : values.entrySet()) { newValues.putIfAbsent(entry.getKey(), entry.getValue()); } ann = new AnnotationValue<>(annotation, newValues); } } } return Optional.ofNullable(ann); } @NonNull @Override public Optional> findDeclaredAnnotation(@NonNull String annotation) { 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) { 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) { return Arrays.stream(hierarchy).anyMatch(am -> am.isTrue(annotation, member)); } @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) { final Class[] classes = Arrays.stream(hierarchy) .flatMap(am -> Stream.of(am.classValues(annotation, member))) .toArray(Class[]::new); return classes; } @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) { return Arrays.stream(hierarchy) .flatMap(am -> am.getAnnotationNamesByStereotype(stereotype).stream()) .collect(Collectors.toList()); } @NonNull @Override public Set getDeclaredAnnotationNames() { return hierarchy[0].getDeclaredAnnotationNames(); } @NonNull @Override public Set getAnnotationNames() { return Arrays.stream(hierarchy) .flatMap(am -> am.getAnnotationNames().stream()) .collect(Collectors.toSet()); } @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) { return Arrays.stream(hierarchy) .flatMap(am -> am.getAnnotationValuesByType(annotationType).stream()) .distinct() .collect(Collectors.toList()); } @NonNull @Override public List> getDeclaredAnnotationValuesByType(@NonNull Class annotationType) { return hierarchy[0].getDeclaredAnnotationValuesByType(annotationType); } @Override public boolean hasDeclaredAnnotation(@Nullable String annotation) { 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) { 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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { final Class[] classes = Arrays.stream(hierarchy) .flatMap(am -> Stream.of(am.classValues(annotation, member))) .toArray(Class[]::new); return classes; } @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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { return Arrays.stream(hierarchy) .flatMap(am -> { if (am instanceof EnvironmentAnnotationMetadata) { return Stream.of(((EnvironmentAnnotationMetadata) am).stringValues(annotation, member, valueMapper)); } return Stream.of(am.stringValues(annotation, member)); }) .toArray(String[]::new); } @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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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) { o = ((EnvironmentAnnotationMetadata) annotationMetadata).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); } private Optional> getAnnotationType(Function>> annotationTypeSupplier) { for (AnnotationMetadata metadata : hierarchy) { final Optional> annotationType = annotationTypeSupplier.apply(metadata); if (annotationType.isPresent()) { return annotationType; } } return Optional.empty(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy