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

com.kasinf.framework.rest.util.ProjectionUtils Maven / Gradle / Ivy

The newest version!
package com.kasinf.framework.rest.util;

import com.kasinf.framework.rest.annotation.Projection;
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.util.ProxyUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author lkhsh
 * 投影工具栏类,借用SpringData Rest中的方法
 */
public final class ProjectionUtils {
    private static final String PROJECTION_ANNOTATION_NOT_FOUND = "在%s上找不到投影注解!手动添加注解或手动将源类型添加到注册中!";
    private final static Set PROJECTION_DEFINITIONS = new HashSet<>();

    /**
     * 添加投影关系
     *
     * @param projectionType 投影类型
     */
    public static void addProjection(Class projectionType) {
        Assert.notNull(projectionType, "Projection的类型不能为null");
        Projection annotation = AnnotationUtils.findAnnotation(projectionType, Projection.class);

        if (annotation == null) {
            throw new IllegalArgumentException(String.format(PROJECTION_ANNOTATION_NOT_FOUND, projectionType));
        }

        String name = annotation.name();
        Class[] sourceTypes = annotation.types();
        if (StringUtils.hasText(name)) {
            addProjection(projectionType, name, sourceTypes);
        } else {
            addProjection(projectionType, sourceTypes);
        }
    }

    /**
     * 添加投影
     *
     * @param projectionType must not be {@literal null}.
     * @param sourceTypes    must not be {@literal null} or empty.
     */
    public static void addProjection(Class projectionType, Class... sourceTypes) {
        Assert.notNull(projectionType, "Projection的类型不能为null");
        addProjection(projectionType, StringUtils.uncapitalize(projectionType.getSimpleName()), sourceTypes);
    }

    /**
     * 添加投影
     *
     * @param projectionType must not be {@literal null}.
     * @param name           must not be {@literal null} or empty.
     * @param sourceTypes    must not be {@literal null} or empty.
     */
    public static void addProjection(Class projectionType, String name, Class... sourceTypes) {

        Assert.notNull(projectionType, "Projection的类型不能为null");
        Assert.hasText(name, "Name不能为null或空");
        Assert.notEmpty(sourceTypes, "源类型不能为null");

        for (Class sourceType : sourceTypes) {
            PROJECTION_DEFINITIONS.add(ProjectionDefinition.of(sourceType, projectionType, name));
        }
    }

    /**
     * 判断目标类型是否有注册的投影
     *
     * @param sourceType 元类型
     * @return boolean
     */
    public static boolean hasProjectionFor(Class sourceType) {

        for (ProjectionDefinition definition : PROJECTION_DEFINITIONS) {
            if (definition.sourceType.isAssignableFrom(sourceType)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取目标类型的投影
     *
     * @param sourceType 源类型
     * @param name 投影名称
     * @return Class
     */
    public static Class getProjectionType(Class sourceType, String name) {
        return getProjectionsFor(sourceType).get(name);
    }

    /**
     * 返回所有目标类型注册的投影
     *
     * @param sourceType must not be {@literal null}.
     * @return Map
     */
    public static Map> getProjectionsFor(Class sourceType) {

        Assert.notNull(sourceType, "目标类型不能为null");

        Class userType = ProxyUtils.getUserClass(sourceType);
        Map byName = new HashMap();
        Map> result = new HashMap>();

        for (ProjectionDefinition entry : PROJECTION_DEFINITIONS) {

            if (!entry.sourceType.isAssignableFrom(userType)) {
                continue;
            }

            ProjectionDefinition existing = byName.get(entry.name);

            if (existing == null || isSubTypeOf(entry.sourceType, existing.sourceType)) {
                byName.put(entry.name, entry);
                result.put(entry.name, entry.targetType);
            }
        }

        return result;
    }

    private static boolean isSubTypeOf(Class left, Class right) {
        return right.isAssignableFrom(left) && !left.equals(right);
    }

    /**
     * 投影定义
     *
     * @author Oliver Gierke
     */
    @Value
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    static final class ProjectionDefinition {

        private final @NonNull Class sourceType, targetType;
        private final @NonNull String name;

        /**
         * Creates a new ProjectionDefinitionKey for the given source type and name;
         *
         * @param sourceType must not be {@literal null}.
         * @param targetType must not be {@literal null}.
         * @param name       must not be {@literal null} or empty.
         */
        static ProjectionUtils.ProjectionDefinition of(Class sourceType, Class targetType, String name) {

            Assert.hasText(name, "Name must not be null or empty!");

            return new ProjectionUtils.ProjectionDefinition(sourceType, targetType, name);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy