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

com.tencent.trpc.spring.util.AnnotationUtils Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/*
 * Tencent is pleased to support the open source community by making tRPC available.
 *
 * Copyright (C) 2023 THL A29 Limited, a Tencent company. 
 * All rights reserved.
 *
 * If you have downloaded a copy of the tRPC source code from Tencent,
 * please note that tRPC source code is licensed under the Apache 2.0 License,
 * A copy of the Apache 2.0 License can be found in the LICENSE file.
 */

package com.tencent.trpc.spring.util;

import static java.lang.String.valueOf;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
import static org.springframework.core.annotation.AnnotatedElementUtils.getMergedAnnotation;
import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
import static org.springframework.core.annotation.AnnotationUtils.getDefaultValue;
import static org.springframework.util.CollectionUtils.isEmpty;
import static org.springframework.util.ObjectUtils.containsElement;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import static org.springframework.util.StringUtils.trimWhitespace;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;

/**
 * Annotation Utilities Class
 *
 * @see org.springframework.core.annotation.AnnotationUtils
 */
public class AnnotationUtils {

    /**
     * Get the attribute value
     *
     * @param attributes {@link AnnotationAttributes the annotation attributes}
     * @param name the name of attribute
     * @param  the type of attribute value
     * @return the attribute value if found
     */
    @SuppressWarnings("unchecked")
    public static  T getAttribute(AnnotationAttributes attributes, String name) {
        return (T) attributes.get(name);
    }

    /**
     * Get the {@link Annotation} attributes
     *
     * @param annotation specified {@link Annotation}
     * @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment}
     * @param ignoreDefaultValue whether ignore default value or not
     * @param ignoreAttributeNames the attribute names of annotation should be ignored
     * @return non-null
     */
    public static Map getAttributes(Annotation annotation,
            PropertyResolver propertyResolver,
            boolean ignoreDefaultValue, String... ignoreAttributeNames) {

        if (annotation == null) {
            return Collections.emptyMap();
        }

        Map attributes = getAnnotationAttributes(annotation);

        Map actualAttributes = new LinkedHashMap<>();

        for (Map.Entry entry : attributes.entrySet()) {

            String attributeName = entry.getKey();
            Object attributeValue = entry.getValue();

            // ignore default attribute value
            if (ignoreDefaultValue && nullSafeEquals(attributeValue,
                    getDefaultValue(annotation, attributeName))) {
                continue;
            }
            actualAttributes.put(attributeName, attributeValue);
        }

        return resolvePlaceholders(actualAttributes, propertyResolver, ignoreAttributeNames);
    }

    /**
     * Resolve the placeholders from the specified annotation attributes
     *
     * @param sourceAnnotationAttributes the source of annotation attributes
     * @param propertyResolver {@link PropertyResolver}
     * @param ignoreAttributeNames the attribute names to be ignored
     * @return a new resolved annotation attributes , non-null and read-only
     */
    public static Map resolvePlaceholders(
            Map sourceAnnotationAttributes,
            PropertyResolver propertyResolver,
            String... ignoreAttributeNames) {

        if (isEmpty(sourceAnnotationAttributes)) {
            return emptyMap();
        }

        Map resolvedAnnotationAttributes = new LinkedHashMap<>();

        for (Map.Entry entry : sourceAnnotationAttributes.entrySet()) {

            String attributeName = entry.getKey();

            // ignore attribute name to skip
            if (containsElement(ignoreAttributeNames, attributeName)) {
                continue;
            }

            Object attributeValue = entry.getValue();

            if (attributeValue instanceof String) {
                attributeValue = resolvePlaceholders(valueOf(attributeValue), propertyResolver);
            } else if (attributeValue instanceof String[]) {
                String[] values = (String[]) attributeValue;
                for (int i = 0; i < values.length; i++) {
                    values[i] = resolvePlaceholders(values[i], propertyResolver);
                }
            }

            resolvedAnnotationAttributes.put(attributeName, attributeValue);
        }

        return unmodifiableMap(resolvedAnnotationAttributes);
    }

    private static String resolvePlaceholders(String attributeValue,
            PropertyResolver propertyResolver) {
        String resolvedValue = attributeValue;
        if (propertyResolver != null) {
            resolvedValue = propertyResolver.resolvePlaceholders(resolvedValue);
            resolvedValue = trimWhitespace(resolvedValue);
        }
        return resolvedValue;
    }

    /**
     * Get {@link AnnotationAttributes the annotation attributes} after merging and resolving the
     * placeholders
     *
     * @param annotatedElement {@link AnnotatedElement the annotated element}
     * @param annotationType the {@link Class tyoe} pf {@link Annotation annotation}
     * @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment}
     * @param ignoreDefaultValue whether ignore default value or not
     * @param ignoreAttributeNames the attribute names of annotation should be ignored
     * @return If the specified annotation type is not found, return null
     */
    public static AnnotationAttributes getMergedAttributes(AnnotatedElement annotatedElement,
            Class annotationType, PropertyResolver propertyResolver,
            boolean ignoreDefaultValue, String... ignoreAttributeNames) {
        Annotation annotation = getMergedAnnotation(annotatedElement, annotationType);
        return annotation == null ? null : fromMap(getAttributes(annotation, propertyResolver,
                ignoreDefaultValue, ignoreAttributeNames));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy