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

shz.spring.api.doc.SpringApiDocGenerator Maven / Gradle / Ivy

There is a newer version: 2023.2.5
Show newest version
package shz.spring.api.doc;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import shz.core.NullHelp;
import shz.core.net.api.ApiMethodAndPath;
import shz.core.net.api.doc.ApiDocGenerator;
import shz.core.net.api.doc.ApiDocRequestModel;
import shz.core.net.api.doc.ApiDocTree;
import shz.core.net.api.doc.ApiDocType;
import shz.spring.BeanContainer;
import shz.spring.api.ApiMethodAndPathGetter;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public abstract class SpringApiDocGenerator extends ApiDocGenerator {
    @Override
    protected ApiMethodAndPath methodAndPath(Class cls, Method method) {
        return ApiMethodAndPathGetter.get(cls, method);
    }

    @Override
    protected boolean isFile(Class cls) {
        return MultipartFile.class.isAssignableFrom(cls);
    }

    @Override
    protected boolean required(Class cls, Field field) {
        return field.isAnnotationPresent(NotBlank.class)
                || field.isAnnotationPresent(NotEmpty.class)
                || field.isAnnotationPresent(NotNull.class);
    }

    @Override
    protected void setRequest(Method method, ApiDocRequestModel request) {
        String[] parameterNames = BeanContainer.getParameterNames(method);
        if (NullHelp.isEmpty(parameterNames)) return;

        List pathVariables = new ArrayList<>();
        List params = new ArrayList<>();
        List parts = new ArrayList<>();
        request.setPathVariables(pathVariables);
        request.setParams(params);
        request.setParts(parts);

        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        Class[] parameterTypes = method.getParameterTypes();
        Type[] genericParameterTypes = method.getGenericParameterTypes();

        Set existParamName = new HashSet<>();
        ApiDocType type;
        if (NullHelp.isEmpty(parameterAnnotations)) {
            for (int i = 0; i < parameterNames.length; ++i) {
                if (existParamName.contains(parameterNames[i])) continue;
                existParamName.add(parameterNames[i]);
                if (Map.class.isAssignableFrom(parameterTypes[i]) || simpleParam(type = type(parameterTypes[i])))
                    params.add(tree(parameterTypes[i], genericParameterTypes[i], Boolean.FALSE, methodParamComment(method, parameterNames[i]), parameterNames[i], null));
                else if (objectParam(type)) {
                    ApiDocTree apiDocTree = tree(parameterTypes[i], genericParameterTypes[i], Boolean.FALSE, methodParamComment(method, parameterNames[i]), parameterNames[i], null);
                    List children = apiDocTree.getChildren();
                    if (NullHelp.nonEmpty(children)) {
                        for (ApiDocTree child : children) {
                            if (existParamName.contains(child.getField())) continue;
                            existParamName.add(child.getField());
                            params.add(child);
                        }
                    }
                }
            }
            return;
        }

        Map requires = new HashMap<>();
        Map values = new HashMap<>();

        Map pathVariablesMap = new HashMap<>();
        int bodyIdx = -1;
        Map paramsMap = new HashMap<>();
        Map partsMap = new HashMap<>();

        boolean mark;
        for (int i = 0; i < parameterNames.length; ++i) {
            mark = false;
            if (NullHelp.nonEmpty(parameterAnnotations[i])) {
                for (Annotation a : parameterAnnotations[i]) {
                    if (a instanceof PathVariable) {
                        PathVariable pathVariable = (PathVariable) a;
                        requires.put(i, pathVariable.required());
                        if (NullHelp.nonBlank(pathVariable.value())) pathVariablesMap.put(i, pathVariable.value());
                        else if (NullHelp.nonBlank(pathVariable.name()))
                            pathVariablesMap.put(i, pathVariable.name());
                        else pathVariablesMap.put(i, parameterNames[i]);
                        mark = true;
                        break;
                    } else if (a instanceof RequestBody) {
                        RequestBody requestBody = (RequestBody) a;
                        requires.put(i, requestBody.required());
                        bodyIdx = i;
                        mark = true;
                        break;
                    } else if (a instanceof RequestParam) {
                        RequestParam requestParam = (RequestParam) a;
                        requires.put(i, requestParam.required());
                        if (!"\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n".equals(requestParam.defaultValue()))
                            values.put(i, requestParam.defaultValue());
                        if (NullHelp.nonBlank(requestParam.value())) paramsMap.put(i, requestParam.value());
                        else if (NullHelp.nonBlank(requestParam.name())) paramsMap.put(i, requestParam.name());
                        else paramsMap.put(i, parameterNames[i]);
                        mark = true;
                        break;
                    } else if (a instanceof RequestAttribute) {
                        RequestAttribute requestAttribute = (RequestAttribute) a;
                        requires.put(i, requestAttribute.required());
                        if (NullHelp.nonBlank(requestAttribute.value()))
                            paramsMap.put(i, requestAttribute.value());
                        else if (NullHelp.nonBlank(requestAttribute.name()))
                            paramsMap.put(i, requestAttribute.name());
                        else paramsMap.put(i, parameterNames[i]);
                        mark = true;
                        break;
                    } else if (a instanceof RequestPart) {
                        RequestPart requestPart = (RequestPart) a;
                        requires.put(i, requestPart.required());
                        if (NullHelp.nonBlank(requestPart.value())) partsMap.put(i, requestPart.value());
                        else if (NullHelp.nonBlank(requestPart.name())) partsMap.put(i, requestPart.name());
                        else partsMap.put(i, parameterNames[i]);
                        mark = true;
                        break;
                    }
                }
            }

            if (!mark) {
                requires.put(i, Boolean.FALSE);
                paramsMap.put(i, parameterNames[i]);
            }
        }

        if (bodyIdx != -1) {
            for (int i = 0; i < parameterNames.length; ++i) {
                if (pathVariablesMap.containsKey(i)) {
                    if (pathVariable(type(parameterTypes[i])))
                        pathVariables.add(tree(parameterTypes[i], genericParameterTypes[i], Boolean.TRUE, methodParamComment(method, parameterNames[i]), pathVariablesMap.get(i), null));
                } else if (i == bodyIdx)
                    request.setBody(tree(parameterTypes[i], genericParameterTypes[i], requires.get(i), methodParamComment(method, parameterNames[i]), null, null));
            }
        } else {
            for (int i = 0; i < parameterNames.length; ++i) {
                if (pathVariablesMap.containsKey(i)) {
                    if (pathVariable(type(parameterTypes[i])))
                        pathVariables.add(tree(parameterTypes[i], genericParameterTypes[i], Boolean.TRUE, methodParamComment(method, parameterNames[i]), pathVariablesMap.get(i), null));
                } else if (partsMap.containsKey(i)) {
                    if (part(type(parameterTypes[i])))
                        parts.add(tree(parameterTypes[i], genericParameterTypes[i], requires.get(i), methodParamComment(method, parameterNames[i]), partsMap.get(i), null));
                } else if (paramsMap.containsKey(i)) {
                    if (existParamName.contains(paramsMap.get(i))) continue;
                    existParamName.add(paramsMap.get(i));
                    if (Map.class.isAssignableFrom(parameterTypes[i]) || simpleParam(type = type(parameterTypes[i])))
                        params.add(tree(parameterTypes[i], genericParameterTypes[i], requires.get(i), methodParamComment(method, parameterNames[i]), paramsMap.get(i), values.get(i)));
                    else if (objectParam(type)) {
                        ApiDocTree apiDocTree = tree(parameterTypes[i], genericParameterTypes[i], requires.get(i), methodParamComment(method, parameterNames[i]), paramsMap.get(i), values.get(i));
                        List children = apiDocTree.getChildren();
                        if (NullHelp.nonEmpty(children)) {
                            for (ApiDocTree child : children) {
                                if (existParamName.contains(child.getField())) continue;
                                existParamName.add(child.getField());
                                params.add(child);
                            }
                        }
                    }
                }
            }
        }
    }

    private boolean simpleParam(ApiDocType type) {
        return type == ApiDocType.string || type == ApiDocType.bool || type == ApiDocType.integer || type == ApiDocType.number || type == ApiDocType.date || type == ApiDocType.file || type == ApiDocType.array;
    }

    private boolean objectParam(ApiDocType type) {
        return type == ApiDocType.object;
    }

    private boolean pathVariable(ApiDocType type) {
        return type == ApiDocType.string || type == ApiDocType.bool || type == ApiDocType.integer || type == ApiDocType.number || type == ApiDocType.date || type == ApiDocType.array;
    }

    private boolean part(ApiDocType type) {
        return type == ApiDocType.file || type == ApiDocType.array;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy