package com.jpsoft.shinestar.advice;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.lang.reflect.Method;
import java.util.Set;

@Aspect
@Component
public class ValidatorAdvice {
    private static Validator validator;

    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Pointcut("(execution(public * com.jpsoft.shinestar..service.*.*(..))) && @annotation(org.springframework.validation.annotation.Validated)")
    private void validateMethod() {

    }

    @Before("validateMethod()")
    public void before(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Method method = signature.getMethod();
        Validated methodMapping = method.getAnnotation(Validated.class);

        if (methodMapping==null){
            return;
        }

        /**
         * 如果加在controller层要增加@Validated注解
         * 如果加载service层执行方法参数的校验,注意接口和实现类都要加注解
        **/
        Set<ConstraintViolation<Object>> constraintViolations = validator.forExecutables().validateParameters(joinPoint.getThis(), signature.getMethod(), args);

        StringBuilder sb = new StringBuilder();

        for (ConstraintViolation<Object> error : constraintViolations) {
            if (sb.length()>0){
                sb.append(";");
            }

            sb.append(error.getMessage());
        }

        if (sb.length()>0) {
            throw new ValidationException(sb.toString());
        }
    }
}
