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

io.micronaut.inject.annotation.AbstractEnvironmentAnnotationMetadata 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.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.context.env.Environment;
import io.micronaut.context.env.PropertyPlaceholderResolver;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.ArgumentUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.core.value.OptionalValues;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Variation of {@link AnnotationMetadata} that is environment specific.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
@Internal
public abstract class AbstractEnvironmentAnnotationMetadata implements AnnotationMetadata {

    private final EnvironmentAnnotationMetadata environmentAnnotationMetadata;

    /**
     * Construct a new environment aware annotation metadata.
     *
     * @param targetMetadata The target annotation metadata
     */
    protected AbstractEnvironmentAnnotationMetadata(AnnotationMetadata targetMetadata) {
        if (targetMetadata instanceof EnvironmentAnnotationMetadata metadata) {
            this.environmentAnnotationMetadata = metadata;
        } else {
            this.environmentAnnotationMetadata = new AnnotationMetadataHierarchy(targetMetadata);
        }
    }

    /**
     * @return The backing annotation metadata
     */
    public AnnotationMetadata getAnnotationMetadata() {
        return environmentAnnotationMetadata;
    }

    @Nullable
    @Override
    public  T synthesize(@NonNull Class annotationClass) {
        return environmentAnnotationMetadata.synthesize(annotationClass);
    }

    @Nullable
    @Override
    public  T synthesizeDeclared(@NonNull Class annotationClass) {
        return environmentAnnotationMetadata.synthesizeDeclared(annotationClass);
    }

    @Override
    public boolean hasEvaluatedExpressions() {
        return environmentAnnotationMetadata.hasEvaluatedExpressions();
    }

    @Override
    public  Optional getValue(@NonNull String annotation, @NonNull String member, @NonNull Argument requiredType) {
        Environment environment = getEnvironment();
        if (environment != null) {
            return environmentAnnotationMetadata.getValue(annotation, member, requiredType, o -> {
                PropertyPlaceholderResolver placeholderResolver = environment.getPlaceholderResolver();
                if (o instanceof String v) {
                    if (v.contains("${")) {
                        return placeholderResolver.resolveRequiredPlaceholders(v);
                    }
                } else if (o instanceof String[] strings) {
                    return AnnotationValue.resolveStringArray(strings, o1 -> {
                        String v = (String) o1;
                        if (v.contains("${")) {
                            return placeholderResolver.resolveRequiredPlaceholders(v);
                        }
                        return v;
                    });
                }
                return o;
            });
        } else {
            return environmentAnnotationMetadata.getValue(annotation, member, requiredType);
        }
    }

    @Override
    public  Class[] classValues(@NonNull String annotation, @NonNull String member) {
        return environmentAnnotationMetadata.classValues(annotation, member);
    }

    @Override
    public  Class[] classValues(@NonNull Class annotation, @NonNull String member) {
        return environmentAnnotationMetadata.classValues(annotation, member);
    }

    @Override
    public boolean isTrue(@NonNull String annotation, @NonNull String member) {
        Environment environment = getEnvironment();
        if (environment != null) {
            return environmentAnnotationMetadata.isTrue(annotation, member, o -> {
                if (o instanceof String v) {
                    if (v.contains("${")) {
                        return environment.getPlaceholderResolver().resolveRequiredPlaceholders(v);
                    }
                }
                return o;
            });
        } else {
            return environmentAnnotationMetadata.isTrue(annotation, member);
        }
    }

    @Override
    public boolean isFalse(@NonNull String annotation, @NonNull String member) {
        Environment environment = getEnvironment();
        if (environment != null) {
            return !environmentAnnotationMetadata.isTrue(annotation, member, o -> {
                if (o instanceof String v) {
                    if (v.contains("${")) {
                        return environment.getPlaceholderResolver().resolveRequiredPlaceholders(v);
                    }
                }
                return o;
            });
        } else {
            return !environmentAnnotationMetadata.isTrue(annotation, member);
        }
    }

    @NonNull
    @Override
    public Optional> getAnnotationTypeByStereotype(@NonNull Class stereotype) {
        return environmentAnnotationMetadata.getAnnotationTypeByStereotype(stereotype);
    }

    @NonNull
    @Override
    public Optional> getAnnotationTypeByStereotype(@Nullable String stereotype) {
        return environmentAnnotationMetadata.getAnnotationTypeByStereotype(stereotype);
    }

    @NonNull
    @Override
    public Optional classValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.classValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public Optional classValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.classValue(annotation, member, valueMapper);
    }

    @Override
    public > Optional enumValue(@NonNull String annotation, @NonNull String member, Class enumType) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.enumValue(annotation, member, enumType, valueMapper);
    }

    @Override
    public > Optional enumValue(@NonNull Class annotation, @NonNull String member, Class enumType) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.enumValue(annotation, member, enumType, valueMapper);
    }

    @Override
    public > E[] enumValues(@NonNull String annotation, @NonNull String member, Class enumType) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.enumValues(annotation, member, enumType, valueMapper);
    }

    @Override
    public Optional booleanValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.booleanValue(annotation, member, valueMapper);

    }

    @Override
    public Optional booleanValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.booleanValue(annotation, member,  valueMapper);
    }

    @NonNull
    @Override
    public Optional stringValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.stringValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public String[] stringValues(@NonNull Class annotation, @NonNull String member) {
        Environment environment = getEnvironment();
        if (environment != null) {

            PropertyPlaceholderResolver resolver = environment.getPlaceholderResolver();
            Function valueMapper = val -> {
                String[] values;
                if (val instanceof CharSequence) {
                    values = new String[] { val.toString() };
                } else if (val instanceof String[] strings) {
                    values = strings;
                } else {
                    return null;
                }
                String[] resolvedValues = Arrays.copyOf(values, values.length);
                boolean expandValues = false;
                for (int i = 0; i < values.length; i++) {
                    String value = values[i];
                    if (value != null && value.contains(resolver.getPrefix())) {
                        value = resolver.resolveRequiredPlaceholders(value);
                        if (value.contains(",")) {
                            expandValues = true;
                        }
                    }
                    resolvedValues[i] = value;
                }
                if (expandValues) {
                    return Stream.of(resolvedValues).flatMap(s -> {
                        if (s.contains(",")) {
                            return Arrays.stream(resolver.resolveRequiredPlaceholder(s, String[].class));
                        }
                        return Stream.of(s);
                    }).toArray(String[]::new);
                } else {
                    return resolvedValues;
                }
            };
            return environmentAnnotationMetadata.stringValues(annotation, member, valueMapper);
        } else {
            return environmentAnnotationMetadata.stringValues(annotation, member, null);
        }
    }

    @NonNull
    @Override
    public Optional stringValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.stringValue(annotation, member, valueMapper);
    }

    @Override
    public OptionalLong longValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.longValue(annotation, member, valueMapper);
    }

    @Override
    public OptionalLong longValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.longValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public OptionalInt intValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.intValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public OptionalInt intValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.intValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public OptionalDouble doubleValue(@NonNull String annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.doubleValue(annotation, member, valueMapper);
    }

    @NonNull
    @Override
    public OptionalDouble doubleValue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.doubleValue(annotation, member, valueMapper);
    }

    @Override
    public boolean isTrue(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return environmentAnnotationMetadata.isTrue(annotation, member, valueMapper);
    }

    @Override
    public boolean isFalse(@NonNull Class annotation, @NonNull String member) {
        Function valueMapper = getEnvironmentValueMapper();
        return !environmentAnnotationMetadata.isTrue(annotation, member, valueMapper);
    }

    @Override
    public @NonNull Optional> getAnnotationType(@NonNull String name) {
        ArgumentUtils.requireNonNull("name", name);
        return environmentAnnotationMetadata.getAnnotationType(name);
    }

    @Override
    public @NonNull Optional> getAnnotationType(@NonNull String name, @NonNull ClassLoader classLoader) {
        ArgumentUtils.requireNonNull("name", name);
        return environmentAnnotationMetadata.getAnnotationType(name, classLoader);
    }

    @Override
    public @NonNull  List> getAnnotationValuesByType(@NonNull Class annotationType) {
        ArgumentUtils.requireNonNull("annotationType", annotationType);
        Environment environment = getEnvironment();
        List> values = environmentAnnotationMetadata.getAnnotationValuesByType(annotationType);
        if (environment != null) {
            return values.stream().map(entries ->
                    new EnvironmentAnnotationValue<>(environment, entries)
            ).collect(Collectors.toList());
        }
        return values;
    }

    @Override
    public @NonNull  List> getDeclaredAnnotationValuesByType(@NonNull Class annotationType) {
        ArgumentUtils.requireNonNull("annotationType", annotationType);
        Environment environment = getEnvironment();
        List> values = environmentAnnotationMetadata.getDeclaredAnnotationValuesByType(annotationType);
        if (environment != null) {
            return values.stream().map(entries -> new EnvironmentAnnotationValue<>(environment, entries))
                    .collect(Collectors.toList());
        }
        return values;
    }

    @SuppressWarnings("unchecked")
    @Override
    public @NonNull  T[] synthesizeAnnotationsByType(@NonNull Class annotationClass) {
        ArgumentUtils.requireNonNull("annotationClass", annotationClass);
        Environment environment = getEnvironment();
        if (environment != null) {

            List> values = environmentAnnotationMetadata.getAnnotationValuesByType(annotationClass);

            return values.stream()
                    .map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, new EnvironmentAnnotationValue<>(environment, entries)))
                    .toArray(value -> (T[]) Array.newInstance(annotationClass, value));
        } else {
            return environmentAnnotationMetadata.synthesizeAnnotationsByType(annotationClass);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public @NonNull  T[] synthesizeDeclaredAnnotationsByType(@NonNull Class annotationClass) {
        ArgumentUtils.requireNonNull("annotationClass", annotationClass);
        Environment environment = getEnvironment();
        if (environment != null) {

            List> values = environmentAnnotationMetadata.getDeclaredAnnotationValuesByType(annotationClass);

            return values.stream()
                    .map(entries -> AnnotationMetadataSupport.buildAnnotation(annotationClass, new EnvironmentAnnotationValue<>(environment, entries)))
                    .toArray(value -> (T[]) Array.newInstance(annotationClass, value));
        } else {
            return environmentAnnotationMetadata.synthesizeDeclaredAnnotationsByType(annotationClass);
        }
    }

    @Override
    public boolean hasDeclaredAnnotation(@Nullable String annotation) {
        return environmentAnnotationMetadata.hasDeclaredAnnotation(annotation);
    }

    @Override
    public boolean hasAnnotation(@Nullable String annotation) {
        return environmentAnnotationMetadata.hasAnnotation(annotation);
    }

    @Override
    public boolean hasStereotype(@Nullable String annotation) {
        return environmentAnnotationMetadata.hasStereotype(annotation);
    }

    @Override
    public boolean hasDeclaredStereotype(@Nullable String annotation) {
        return environmentAnnotationMetadata.hasDeclaredStereotype(annotation);
    }

    @Override
    public @NonNull List getAnnotationNamesByStereotype(String stereotype) {
        return environmentAnnotationMetadata.getAnnotationNamesByStereotype(stereotype);
    }

    @Override
    public @NonNull Set getAnnotationNames() {
        return environmentAnnotationMetadata.getAnnotationNames();
    }

    @Override
    public @NonNull Set getDeclaredAnnotationNames() {
        return environmentAnnotationMetadata.getDeclaredAnnotationNames();
    }

    @Override
    public @NonNull List getDeclaredAnnotationNamesByStereotype(String stereotype) {
        return environmentAnnotationMetadata.getDeclaredAnnotationNamesByStereotype(stereotype);
    }

    @Override
    public @NonNull  Optional> findAnnotation(@NonNull String annotation) {
        ArgumentUtils.requireNonNull("annotation", annotation);
        Environment env = getEnvironment();

        Optional> values = environmentAnnotationMetadata.findAnnotation(annotation);

        if (env != null) {
            return values.map(av -> new EnvironmentAnnotationValue<>(env, av));
        }
        return values;
    }

    @Override
    public @NonNull  Optional> findDeclaredAnnotation(@NonNull String annotation) {
        ArgumentUtils.requireNonNull("annotation", annotation);
        Environment env = getEnvironment();

        Optional> values = environmentAnnotationMetadata.findDeclaredAnnotation(annotation);

        if (env != null) {
            return values.map(av -> new EnvironmentAnnotationValue<>(env, av));
        }
        return values;
    }

    @Override
    public @NonNull  OptionalValues getValues(@NonNull String annotation, @NonNull Class valueType) {
        ArgumentUtils.requireNonNull("annotation", annotation);
        ArgumentUtils.requireNonNull("valueType", valueType);

        if (environmentAnnotationMetadata instanceof DefaultAnnotationMetadata) {
            Environment environment = getEnvironment();
            return resolveOptionalValuesForEnvironment(
                    annotation,
                    valueType,
                    Collections.singleton(environmentAnnotationMetadata),
                    environment
            );
        } else if (environmentAnnotationMetadata instanceof AnnotationMetadataHierarchy hierarchy) {
            Environment environment = getEnvironment();
            return resolveOptionalValuesForEnvironment(
                    annotation,
                    valueType,
                    hierarchy,
                    environment
            );

        }
        return OptionalValues.empty();
    }

    @Override
    public @NonNull  Optional getDefaultValue(@NonNull String annotation, @NonNull String member, @NonNull Class requiredType) {
        return environmentAnnotationMetadata.getDefaultValue(annotation, member, requiredType);
    }

    @Override
    public @NonNull  Optional getDefaultValue(@NonNull String annotation, @NonNull String member, @NonNull Argument requiredType) {
        return environmentAnnotationMetadata.getDefaultValue(annotation, member, requiredType);
    }

    @Override
    public AnnotationMetadata copyAnnotationMetadata() {
        return environmentAnnotationMetadata.copyAnnotationMetadata();
    }

    @Override
    public AnnotationMetadata getTargetAnnotationMetadata() {
        return environmentAnnotationMetadata.getTargetAnnotationMetadata();
    }

    /**
     * Resolves the {@link Environment} for this metadata.
     *
     * @return The metadata
     */
    protected abstract @Nullable Environment getEnvironment();

    /**
     * @return The value mapper for the environment
     */
    private @Nullable Function getEnvironmentValueMapper() {
        Environment env = getEnvironment();
        if (env != null) {
            return o -> {
                if (o instanceof String v) {
                    if (v.contains("${")) {
                        return env.getPlaceholderResolver().resolveRequiredPlaceholders(v);
                    }
                }
                return o;
            };
        }
        return null;
    }

    private  OptionalValues resolveOptionalValuesForEnvironment(
            String annotation,
            Class valueType,
            Iterable metadata,
            Environment environment) {

        Map finalValues = new LinkedHashMap<>();
        for (AnnotationMetadata annotationMetadata : metadata) {
            if (annotationMetadata instanceof DefaultAnnotationMetadata defaultAnnotationMetadata) {

                Map> allAnnotations = defaultAnnotationMetadata.allAnnotations;
                Map> allStereotypes = defaultAnnotationMetadata.allStereotypes;
                if (allAnnotations != null && StringUtils.isNotEmpty(annotation)) {
                    processMap(annotation, finalValues, allStereotypes);
                    processMap(annotation, finalValues, allAnnotations);
                }
            }
        }

        if (environment != null) {
            return new EnvironmentOptionalValuesMap<>(valueType, finalValues, environment);
        } else {
            return OptionalValues.of(valueType, finalValues);
        }
    }

    private void processMap(String annotation, Map finalValues, Map> allStereotypes) {
        if (allStereotypes != null) {
            Map values = allStereotypes.get(annotation);
            if (values != null) {
                for (Map.Entry entry : values.entrySet()) {
                    finalValues.putIfAbsent(entry.getKey(), entry.getValue());
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy