package com.keyware.shandan.frame.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author Administrator
 */
public class AspectCommon {
    /**
     * 获得注解
     *
     * @param joinPoint       切面连接点
     * @param annotationClass
     * @return
     */
    public static <T extends Annotation> T getAnnotationByMethod(JoinPoint joinPoint, Class<T> annotationClass) throws NoSuchMethodException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 这里获取目标对象的实际方法，而非代理对象的方法
        Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
        return method.getAnnotation(annotationClass);
    }

    /**
     * 获取方法所在类对应的实体类型
     *
     * @param joinPoint -
     * @return -
     */
    public static Class<?> geTargetClassTType(ProceedingJoinPoint joinPoint) {
        return checkType(joinPoint.getTarget().getClass().getGenericSuperclass(), 1);
    }

    public static Class<?> getMethodReturnType(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getReturnType();
    }

    /**
     * 获取类上的泛型T
     *
     * @param type  类
     * @param index 泛型索引
     */
    public static Class<?> checkType(Type type, int index) {
        if (type instanceof Class<?>) {
            return (Class<?>) type;
        } else if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;
            Type[] pts = pt.getActualTypeArguments();
            if (index < pts.length) {
                return checkType(pts[index], index);
            }
        } else {
            String className = type == null ? "null" : type.getClass().getName();
            throw new IllegalArgumentException("Expected a Class, ParameterizedType"
                    + ", but <" + type + "> is of type " + className);
        }
        return null;
    }
}
