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

io.micronaut.inject.qualifiers.Qualifiers Maven / Gradle / Ivy

/*
 * 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.qualifiers;

import io.micronaut.context.Qualifier;
import io.micronaut.context.annotation.Any;
import io.micronaut.context.annotation.Type;
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.UsedByGeneratedCode;
import io.micronaut.core.util.StringUtils;
import jakarta.inject.Named;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * Factory for {@link io.micronaut.context.annotation.Bean} qualifiers.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
public class Qualifiers {

    /**
     * Allows looking up the first matching instance.
     *
     * 

This qualifier results on {@link io.micronaut.context.exceptions.NonUniqueBeanException} never being thrown as * the first matching instance will be returned.

* * @param The generic type * @return The any qualifier. * @see Any * @since 3.0.0 */ @SuppressWarnings("unchecked") public static Qualifier any() { return AnyQualifier.INSTANCE; } /** * Build a qualifier for the given argument. * * @param argument The argument * @param The type * @return The resolved qualifier */ @SuppressWarnings("unchecked") public static @Nullable Qualifier forArgument(@NonNull Argument argument) { AnnotationMetadata annotationMetadata = Objects.requireNonNull(argument, "Argument cannot be null").getAnnotationMetadata(); boolean hasMetadata = annotationMetadata != AnnotationMetadata.EMPTY_METADATA; List qualifierTypes = hasMetadata ? annotationMetadata.getAnnotationNamesByStereotype(AnnotationUtil.QUALIFIER) : null; if (CollectionUtils.isNotEmpty(qualifierTypes)) { if (qualifierTypes.size() == 1) { return Qualifiers.byAnnotation( annotationMetadata, qualifierTypes.iterator().next() ); } else { Qualifier[] qualifiers = new Qualifier[qualifierTypes.size()]; int i = 0; for (String type : qualifierTypes) { qualifiers[i++] = Qualifiers.byAnnotation(annotationMetadata, type); } return Qualifiers.byQualifiers(qualifiers); } } return null; } /** * Build a qualifier from other qualifiers. * * @param qualifiers The qualifiers * @param The component type * @return The qualifier */ public static Qualifier byQualifiers(Qualifier... qualifiers) { return new CompositeQualifier<>(qualifiers); } /** * Build a qualifier for the given name. * * @param name The name * @param The component type * @return The qualifier */ @UsedByGeneratedCode public static Qualifier byName(String name) { return new NameQualifier<>(null, name); } /** * Build a qualifier for the given annotation. * * @param annotation The annotation * @param The component type * @return The qualifier */ public static Qualifier byAnnotation(Annotation annotation) { if (annotation instanceof Type) { Type typeAnn = (Type) annotation; return byType(typeAnn.value()); } else if (annotation instanceof Named) { Named nameAnn = (Named) annotation; return byName(nameAnn.value()); } else if (annotation instanceof Any) { //noinspection unchecked return AnyQualifier.INSTANCE; } else { return new AnnotationQualifier<>(annotation); } } /** * Build a qualifier for the given annotation. * * @param metadata The metadata * @param type The annotation type * @param The component type * @return The qualifier */ public static Qualifier byAnnotation(AnnotationMetadata metadata, Class type) { if (Any.class == type) { //noinspection unchecked return AnyQualifier.INSTANCE; } else if (Type.class == type) { Optional aClass = metadata.classValue(type); if (aClass.isPresent()) { return byType(aClass.get()); } } else if (Named.class == type || AnnotationUtil.NAMED.equals(type.getName())) { Optional value = metadata.stringValue(type); if (value.isPresent()) { return byName(value.get()); } } return new AnnotationMetadataQualifier<>(metadata, type); } /** *

Build a qualifier for the given annotation. This qualifier will match a candidate under the following * circumstances:

* *
    *
  • If the type parameter is {@link Named} then the value of the {@link Named} annotation within the metadata is used to match the candidate by name
  • *
  • If the type parameter is {@link Type} then the value of the {@link Type} annotation is used to match the candidate by type
  • *
* * @param metadata The metadata * @param type The annotation type * @param The component type * @return The qualifier */ public static Qualifier byAnnotation(AnnotationMetadata metadata, String type) { if (Type.NAME.equals(type)) { Optional aClass = metadata.classValue(type); if (aClass.isPresent()) { return byType(aClass.get()); } } else if (Any.NAME.equals(type)) { //noinspection unchecked return AnyQualifier.INSTANCE; } else if (Named.class.getName().equals(type) || AnnotationUtil.NAMED.equals(type)) { String n = metadata.stringValue(type).orElse(null); if (n != null) { return byName(n); } } return new AnnotationMetadataQualifier<>(metadata, type); } /** *

Builds a qualifier that uses the given repeatable annotation.

* * @param metadata The metadata * @param repeatableType The annotation repeatable type. That is the annotation specified to {@link java.lang.annotation.Repeatable#value()} * @param The component type * @return The qualifier */ @UsedByGeneratedCode public static Qualifier byRepeatableAnnotation(AnnotationMetadata metadata, String repeatableType) { return new RepeatableAnnotationQualifier<>(metadata, repeatableType); } /** *

Build a qualifier for the given annotation.

* *

Unlike {@link #byAnnotation(io.micronaut.core.annotation.AnnotationMetadata, String)} this method will not attempt to pick the qualifier strategy to use at runtime based on the passed annotation name.

* * @param metadata The metadata * @param type The annotation type * @param The component type * @return The qualifier * @since 3.1.0 */ @UsedByGeneratedCode @Internal public static Qualifier byAnnotationSimple(AnnotationMetadata metadata, String type) { return new AnnotationMetadataQualifier<>(metadata, type); } /** * Build a qualifier for the given annotation. * * @param stereotype The stereotype * @param The component type * @return The qualifier */ public static Qualifier byStereotype(Class stereotype) { return new AnnotationStereotypeQualifier<>(stereotype); } /** * Build a qualifier for the given annotation. * * @param stereotype The stereotype * @param The component type * @return The qualifier * @since 3.0.0 */ public static Qualifier byStereotype(String stereotype) { return new NamedAnnotationStereotypeQualifier<>(stereotype); } /** * Build a qualifier for the given generic type arguments. * * @param typeArguments The generic type arguments * @param The component type * @return The qualifier */ public static Qualifier byTypeArguments(Class... typeArguments) { return new TypeArgumentQualifier<>(typeArguments); } /** * Build a qualifier for the given generic type argument name. * * @param typeName The name of the generic type argument * @param The component type * @return The qualifier * @since 3.0.0 */ public static @NonNull Qualifier byExactTypeArgumentName(@NonNull String typeName) { return new ExactTypeArgumentNameQualifier<>(typeName); } /** * Build a qualifier for the given generic type arguments. Only the closest * matches will be returned. * * @param typeArguments The generic type arguments * @param The component type * @return The qualifier */ public static Qualifier byTypeArgumentsClosest(Class... typeArguments) { return new ClosestTypeArgumentQualifier<>(typeArguments); } /** * Build a qualifier for the given generic type arguments. * * @param typeArguments The generic type arguments * @param The component type * @return The qualifier */ public static Qualifier byType(Class... typeArguments) { return new TypeAnnotationQualifier<>(typeArguments); } /** * Reduces bean definitions by the given interceptor binding. * * @param annotationMetadata The annotation metadata * @param The bean type * @return The qualifier */ public static @NonNull Qualifier byInterceptorBinding(@NonNull AnnotationMetadata annotationMetadata) { return new InterceptorBindingQualifier<>(annotationMetadata); } /** * Reduces bean definitions by the given interceptor binding. * * @param bindingAnnotationNames The binding annotation names * @param The bean type * @return The qualifier * @since 3.0.0 * @deprecated Use {@link #byInterceptorBindingValues(java.util.Collection)} */ @Deprecated public static @NonNull Qualifier byInterceptorBinding(@NonNull Collection bindingAnnotationNames) { return new InterceptorBindingQualifier<>(bindingAnnotationNames.toArray(StringUtils.EMPTY_STRING_ARRAY)); } /** * Reduces bean definitions by the given interceptor binding. * * @param binding The binding values to use * @param The bean type * @return The qualifier * @since 3.3.0 */ public static @NonNull Qualifier byInterceptorBindingValues(@NonNull Collection> binding) { return new InterceptorBindingQualifier<>(binding); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy