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

com.ly.doc.template.IRestDocTemplate Maven / Gradle / Ivy

Go to download

Smart-doc is a tool that supports both JAVA RESTFUL API and Apache Dubbo RPC interface document generation.

There is a newer version: 3.0.5
Show newest version
/*
 * Copyright (C) 2018-2023 smart-doc
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.ly.doc.template;

import com.ly.doc.constants.*;
import com.ly.doc.model.*;
import com.ly.doc.utils.*;
import com.power.common.util.*;
import com.ly.doc.builder.ProjectDocConfigBuilder;
import com.ly.doc.handler.IHeaderHandler;
import com.ly.doc.handler.IRequestMappingHandler;
import com.ly.doc.helper.FormDataBuildHelper;
import com.ly.doc.helper.JsonBuildHelper;
import com.ly.doc.helper.ParamsBuildHelper;
import com.ly.doc.model.annotation.EntryAnnotation;
import com.ly.doc.model.annotation.FrameworkAnnotations;
import com.ly.doc.model.annotation.MappingAnnotation;
import com.ly.doc.model.request.ApiRequestExample;
import com.ly.doc.model.request.CurlRequest;
import com.ly.doc.model.request.RequestMapping;
import com.thoughtworks.qdox.model.*;
import com.thoughtworks.qdox.model.expression.AnnotationValue;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ly.doc.constants.DocGlobalConstants.FILE_CONTENT_TYPE;
import static com.ly.doc.constants.DocGlobalConstants.JSON_CONTENT_TYPE;
import static com.ly.doc.constants.DocTags.IGNORE;

public interface IRestDocTemplate extends IBaseDocBuildTemplate {

    Logger log = Logger.getLogger(IRestDocTemplate.class.getName());
    AtomicInteger atomicInteger = new AtomicInteger(1);

    default List processApiData(ProjectDocConfigBuilder projectBuilder, FrameworkAnnotations frameworkAnnotations,
                                        List configApiReqParams, IRequestMappingHandler baseMappingHandler, IHeaderHandler headerHandler,
                                        Collection javaClasses) {
        ApiConfig apiConfig = projectBuilder.getApiConfig();
        List apiDocList = new ArrayList<>();
        int order = 0;
        boolean setCustomOrder = false;
        // exclude  class is ignore
        for (JavaClass cls : javaClasses) {
            if (StringUtil.isNotEmpty(apiConfig.getPackageFilters())) {
                // from smart config
                if (!DocUtil.isMatch(apiConfig.getPackageFilters(), cls)) {
                    continue;
                }
            }
            // from tag
            DocletTag ignoreTag = cls.getTagByName(DocTags.IGNORE);
            if (!isEntryPoint(cls, frameworkAnnotations) || Objects.nonNull(ignoreTag)) {
                continue;
            }
            String strOrder = JavaClassUtil.getClassTagsValue(cls, DocTags.ORDER, Boolean.TRUE);
            order++;
            if (ValidateUtil.isNonNegativeInteger(strOrder)) {
                setCustomOrder = true;
                order = Integer.parseInt(strOrder);
            }

            List apiMethodDocs = buildEntryPointMethod(cls, apiConfig, projectBuilder,
                    frameworkAnnotations, configApiReqParams, baseMappingHandler, headerHandler);
            this.handleApiDoc(cls, apiDocList, apiMethodDocs, order, apiConfig.isMd5EncryptedHtmlName());
        }
        apiDocList = handleTagsApiDoc(apiDocList);
        if (apiConfig.isSortByTitle()) {
            Collections.sort(apiDocList);
        } else if (setCustomOrder) {
            // while set custom oder
            return apiDocList.stream()
                    .sorted(Comparator.comparing(ApiDoc::getOrder))
                    .peek(p -> p.setOrder(atomicInteger.getAndAdd(1))).collect(Collectors.toList());
        }
        return apiDocList;
    }

    default String createDocRenderHeaders(List headers, boolean isAdoc) {
        StringBuilder builder = new StringBuilder();
        if (CollectionUtil.isEmpty(headers)) {
            headers = new ArrayList<>(0);
        }
        for (ApiReqParam header : headers) {
            builder.append("|")
                    .append(header.getName()).append("|")
                    .append(header.getType()).append("|")
                    .append(header.isRequired()).append("|")
                    .append(header.getDesc()).append("|")
                    .append(header.getSince()).append("|\n");
        }
        return builder.toString();
    }


    default void handleApiDoc(JavaClass cls, List apiDocList, List apiMethodDocs, int order, boolean isUseMD5) {
        String controllerName = cls.getName();
        ApiDoc apiDoc = new ApiDoc();
        String classAuthor = JavaClassUtil.getClassTagsValue(cls, DocTags.AUTHOR, Boolean.TRUE);
        apiDoc.setOrder(order);
        apiDoc.setName(controllerName);
        apiDoc.setAuthor(classAuthor);
        apiDoc.setAlias(controllerName);
        apiDoc.setFolder(true);
        apiDoc.setPackageName(cls.getPackage().getName());
        // apiDoc.setAuthor();

        // handle class tags
        List classTags = cls.getTagsByName(DocTags.TAG);
        Set tagSet = classTags.stream().map(DocletTag::getValue)
                .map(StringUtils::trim)
                .collect(Collectors.toCollection(LinkedHashSet::new));
        String[] tags = tagSet.toArray(new String[]{});
        apiDoc.setTags(tags);

        if (isUseMD5) {
            String name = DocUtil.generateId(apiDoc.getName());
            apiDoc.setAlias(name);
        }
        String desc = DocUtil.getEscapeAndCleanComment(cls.getComment());
        apiDoc.setDesc(desc);
        apiDoc.setList(apiMethodDocs);
        apiDocList.add(apiDoc);

        tagSet.add(StringUtils.trim(desc));
        for (String tag : tagSet) {
            DocMapping.tagDocPut(tag, apiDoc, null);
            for (ApiMethodDoc methodDoc : apiMethodDocs) {
                DocMapping.tagDocPut(tag, null, methodDoc);
            }
        }
        for (ApiMethodDoc methodDoc : apiMethodDocs) {
            String[] docTags = methodDoc.getTags();
            methodDoc.setClazzDoc(apiDoc);
            if (ArrayUtils.isEmpty(docTags)) continue;
            for (String tag : docTags) {
                DocMapping.tagDocPut(tag, null, methodDoc);
            }
        }
    }


    default void mappingParamToApiParam(String str, List paramList, Map mappingParams) {
        String param = StringUtil.removeQuotes(str);
        String paramName;
        String paramValue;
        String description = "Parameter condition.";
        if (param.contains("=")) {
            int index = param.indexOf("=");
            paramName = param.substring(0, index);
            paramValue = param.substring(index + 1);
            description = description + " [" + paramName + "=" + paramValue + "]";
        } else {
            paramName = param;
            paramValue = DocUtil.getValByTypeAndFieldName("string", paramName, Boolean.TRUE);
        }
        String type = ValidateUtil.isPositiveInteger(paramValue) ? "int32" : "string";
        ApiParam apiParam = ApiParam.of().setField(paramName)
                .setId(paramList.size() + 1)
                .setQueryParam(true)
                .setValue(paramValue)
                .setType(type).setDesc(description)
                .setRequired(true)
                .setVersion(DocGlobalConstants.DEFAULT_VERSION);
        paramList.add(apiParam);
        mappingParams.put(paramName, null);
    }

    default void mappingParamProcess(String str, Map pathParamsMap) {
        String param = StringUtil.removeQuotes(str);
        String paramName;
        String paramValue;
        if (param.contains("=")) {
            int index = param.indexOf("=");
            paramName = param.substring(0, index);
            paramValue = param.substring(index + 1);
            pathParamsMap.put(paramName, paramValue);
        } else {
            paramName = param;
            pathParamsMap.put(paramName, DocUtil.getValByTypeAndFieldName("string", paramName, Boolean.TRUE));
        }
    }


    default String getParamName(String paramName, JavaAnnotation annotation) {
        String resolvedParamName = DocUtil.resolveAnnotationValue(annotation.getProperty(DocAnnotationConstants.VALUE_PROP));
        if (StringUtils.isBlank(resolvedParamName)) {
            resolvedParamName = DocUtil.resolveAnnotationValue(annotation.getProperty(DocAnnotationConstants.NAME_PROP));
        }
        if (!StringUtils.isBlank(resolvedParamName)) {
            paramName = StringUtil.removeQuotes(resolvedParamName);
        }
        return StringUtil.removeQuotes(paramName);
    }

    default List handleTagsApiDoc(List apiDocList) {
        if (CollectionUtil.isEmpty(apiDocList)) {
            return Collections.emptyList();
        }

        // all class tag copy
        Map copyMap = new HashMap<>();
        apiDocList.forEach(doc -> {
            String[] tags = doc.getTags();
            if (ArrayUtils.isEmpty(tags)) {
                tags = new String[]{doc.getPackageName() + "." + doc.getName()};
            }

            for (String tag : tags) {
                tag = StringUtil.trim(tag);
                copyMap.computeIfPresent(tag, (k, v) -> {
                    List list = CollectionUtil.isEmpty(v.getList()) ? new ArrayList<>() : v.getList();
                    list.addAll(doc.getList());
                    v.setList(list);
                    return v;
                });
                copyMap.putIfAbsent(tag, doc);
            }
        });

        // handle method tag
        Map allMap = new HashMap<>(copyMap);
        allMap.forEach((k, v) -> {
            List methodDocList = v.getList();
            methodDocList.forEach(method -> {
                String[] tags = method.getTags();
                if (ArrayUtils.isEmpty(tags)) {
                    return;
                }
                for (String tag : tags) {
                    tag = StringUtil.trim(tag);
                    copyMap.computeIfPresent(tag, (k1, v2) -> {
                        method.setOrder(v2.getList().size() + 1);
                        v2.getList().add(method);
                        return v2;
                    });
                    copyMap.putIfAbsent(tag, ApiDoc.buildTagApiDoc(v, tag, method));
                }
            });
        });

        List apiDocs = new ArrayList<>(copyMap.values());
        int index = apiDocs.size() - 1;
        for (ApiDoc apiDoc : apiDocs) {
            if (apiDoc.getOrder() == null) {
                apiDoc.setOrder(index++);
            }
        }
        apiDocs.sort(Comparator.comparing(ApiDoc::getOrder));
        return apiDocs;
    }

    default List getClassAnnotations(JavaClass cls, FrameworkAnnotations frameworkAnnotations) {
        List annotationsList = new ArrayList<>(cls.getAnnotations());
        Map entryAnnotationMap = frameworkAnnotations.getEntryAnnotations();
        Map mappingAnnotationMap = frameworkAnnotations.getMappingAnnotations();
        boolean flag = annotationsList.stream().anyMatch(item -> {
            String annotationName = item.getType().getValue();
            String fullyName = item.getType().getFullyQualifiedName();
            return (entryAnnotationMap.containsKey(annotationName) || entryAnnotationMap.containsKey(fullyName))&&
                    (mappingAnnotationMap.containsKey(annotationName)||mappingAnnotationMap.containsKey(fullyName));
        });
        // child override parent set
        if (flag) {
            return annotationsList;
        }
        JavaClass superJavaClass = cls.getSuperJavaClass();
        if (Objects.nonNull(superJavaClass) && !"Object".equals(superJavaClass.getSimpleName())) {
            annotationsList.addAll(getClassAnnotations(superJavaClass, frameworkAnnotations));
        }
        List interfaseList = cls.getInterfaces();
        if(CollectionUtil.isNotEmpty(interfaseList)){
            for (JavaClass javaInterface : interfaseList) {
                annotationsList.addAll(getClassAnnotations(javaInterface,frameworkAnnotations));
            }
        }
        return annotationsList;
    }

    default List buildEntryPointMethod(
            final JavaClass cls, ApiConfig apiConfig,
            ProjectDocConfigBuilder projectBuilder,
            FrameworkAnnotations frameworkAnnotations,
            List configApiReqParams,
            IRequestMappingHandler baseMappingHandler,
            IHeaderHandler headerHandler) {
        String clazName = cls.getCanonicalName();
        boolean paramsDataToTree = projectBuilder.getApiConfig().isParamsDataToTree();
        String group = JavaClassUtil.getClassTagsValue(cls, DocTags.GROUP, Boolean.TRUE);
        List classAnnotations = this.getClassAnnotations(cls, frameworkAnnotations);
        String baseUrl = "";
        // the requestMapping annotation's consumes value on class
        String classMediaType = null;
        Map mappingAnnotationMap = frameworkAnnotations.getMappingAnnotations();
        for (JavaAnnotation annotation : classAnnotations) {
            String annotationName = annotation.getType().getValue();
            MappingAnnotation mappingAnnotation = mappingAnnotationMap.get(annotationName);
            if (Objects.isNull(mappingAnnotation)) {
                continue;
            }
            if (CollectionUtil.isNotEmpty(mappingAnnotation.getPathProps())) {
                baseUrl = StringUtil.removeQuotes(DocUtil.getPathUrl(annotation, mappingAnnotation.getPathProps()
                        .toArray(new String[0])));
            }
            // use first annotation's value
            if (classMediaType == null) {
                Object consumes = annotation.getNamedParameter(mappingAnnotation.getConsumesProp());
                if (consumes != null) {
                    classMediaType = consumes.toString();
                }
            }
        }

        Set filterMethods = DocUtil.findFilterMethods(clazName);
        boolean needAllMethods = filterMethods.contains(DocGlobalConstants.DEFAULT_FILTER_METHOD);

        List methods = cls.getMethods();
        List docJavaMethods = new ArrayList<>(methods.size());
        for (JavaMethod method : methods) {
            if (method.isPrivate() || DocUtil.isMatch(apiConfig.getPackageExcludeFilters(), clazName + "." + method.getName())) {
                continue;
            }
            if (Objects.nonNull(method.getTagByName(IGNORE))) {
                continue;
            }
            if (needAllMethods || filterMethods.contains(method.getName())) {
                docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, null));
            }
        }
        // add parent class methods
        docJavaMethods.addAll(getParentsClassMethods(apiConfig, projectBuilder, cls));
        List implClasses = cls.getImplements();
        for (JavaType type : implClasses) {
            JavaClass javaClass = (JavaClass) type;
            Map actualTypesMap = JavaClassUtil.getActualTypesMap(javaClass);
            for (JavaMethod method : javaClass.getMethods()) {
                if (method.isDefault()) {
                    docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, actualTypesMap));
                }
            }
        }
        // call ICustomJavaMethodHandler
        if (apiConfig.getCustomJavaMethodHandler() != null) {
            docJavaMethods = apiConfig.getCustomJavaMethodHandler().apply(cls, docJavaMethods);
        }
        List methodDocList = new ArrayList<>(methods.size());
        int methodOrder = 0;
        for (DocJavaMethod docJavaMethod : docJavaMethods) {
            JavaMethod method = docJavaMethod.getJavaMethod();
            // handle request mapping
            RequestMapping requestMapping = baseMappingHandler.handle(projectBuilder, baseUrl,
                    method, frameworkAnnotations,
                    (javaClass, mapping) -> this.requestMappingPostProcess(javaClass, method, mapping));
            if (Objects.isNull(requestMapping)) {
                continue;
            }
            if (Objects.isNull(requestMapping.getShortUrl())) {
                continue;
            }
            ApiMethodDoc apiMethodDoc = new ApiMethodDoc();
            // fill contentType by annotation's consumes parameter
            String mediaType = requestMapping.getMediaType();
            if (Objects.nonNull(mediaType)) {
                apiMethodDoc.setContentType(MediaType.valueOf(mediaType));
            } else if (Objects.nonNull(classMediaType)) {
                // if method does not contain consumes parameter, then use the value of class
                apiMethodDoc.setContentType(MediaType.valueOf(classMediaType));
            }
            apiMethodDoc.setDownload(docJavaMethod.isDownload());
            apiMethodDoc.setPage(docJavaMethod.getPage());
            apiMethodDoc.setGroup(group);
            apiMethodDoc.setVersion(docJavaMethod.getVersion());
            if (Objects.nonNull(docJavaMethod.getGroup())) {
                apiMethodDoc.setGroup(docJavaMethod.getGroup());
            }

            // handle tags
            List tags = method.getTagsByName(DocTags.TAG);
            apiMethodDoc.setTags(tags.stream().map(DocletTag::getValue).toArray(String[]::new));

            methodOrder++;
            apiMethodDoc.setOrder(methodOrder);
            apiMethodDoc.setName(method.getName());
            String common = method.getComment();
            if (StringUtil.isEmpty(common)) {
                common = JavaClassUtil.getSameSignatureMethodCommonFromInterface(cls, method);
            }
            apiMethodDoc.setDesc(common);
            apiMethodDoc.setAuthor(docJavaMethod.getAuthor());
            apiMethodDoc.setDetail(docJavaMethod.getDetail());
            String methodUid = DocUtil.generateId(clazName + method.getName() + methodOrder);
            apiMethodDoc.setMethodId(methodUid);
            // handle headers
            List apiReqHeaders = headerHandler.handle(method, projectBuilder);
            apiReqHeaders = apiReqHeaders.stream().filter(param -> DocUtil.filterPath(requestMapping, param)).collect(Collectors.toList());

            apiMethodDoc.setType(requestMapping.getMethodType());
            apiMethodDoc.setUrl(requestMapping.getUrl());
            apiMethodDoc.setServerUrl(projectBuilder.getServerUrl());
            apiMethodDoc.setPath(requestMapping.getShortUrl());
            apiMethodDoc.setDeprecated(requestMapping.isDeprecated());

            final List apiReqParamList = configApiReqParams.stream()
                    .filter(param -> DocUtil.filterPath(requestMapping, param)).collect(Collectors.toList());

            // build request params
            ApiMethodReqParam apiMethodReqParam = requestParams(docJavaMethod, projectBuilder, apiReqParamList, frameworkAnnotations);
            apiMethodDoc.setPathParams(apiMethodReqParam.getPathParams());
            apiMethodDoc.setQueryParams(apiMethodReqParam.getQueryParams());
            apiMethodDoc.setRequestParams(apiMethodReqParam.getRequestParams());

            if (paramsDataToTree) {
                // convert to tree
                this.convertParamsDataToTree(apiMethodDoc);
            }
            List allApiReqHeaders;
            final Map> reqParamMap = configApiReqParams.stream().collect(Collectors.groupingBy(ApiReqParam::getParamIn));
            final List headerParamList = reqParamMap.getOrDefault(ApiReqParamInTypeEnum.HEADER.getValue(), Collections.emptyList());
            allApiReqHeaders = Stream.of(headerParamList, apiReqHeaders).filter(Objects::nonNull)
                    .flatMap(Collection::stream).distinct().filter(param -> DocUtil.filterPath(requestMapping, param)).collect(Collectors.toList());

            // reduce create in template
            apiMethodDoc.setHeaders(this.createDocRenderHeaders(allApiReqHeaders, apiConfig.isAdoc()));
            apiMethodDoc.setRequestHeaders(allApiReqHeaders);
            String path = apiMethodDoc.getPath().split(";")[0];
            String pathUrl = DocUtil.formatPathUrl(path);
            List pathParams = apiMethodDoc.getPathParams();
            Iterator pathIterator = pathParams.iterator();
            while (pathIterator.hasNext()) {
                ApiParam next = pathIterator.next();
                String pathKey = "{" + next.getField() + "}";
                if (!pathUrl.contains(pathKey)) {
                    pathIterator.remove();
                }
            }

            // build request json
            ApiRequestExample requestExample = buildReqJson(docJavaMethod, apiMethodDoc, requestMapping.getMethodType(),
                    projectBuilder, frameworkAnnotations);
            String requestJson = requestExample.getExampleBody();
            // set request example detail
            apiMethodDoc.setRequestExample(requestExample);
            apiMethodDoc.setRequestUsage(requestJson == null ? requestExample.getUrl() : requestJson);
            // build response usage
            String responseValue = DocUtil.getNormalTagComments(method, DocTags.API_RESPONSE, cls.getName());
            if (StringUtil.isNotEmpty(responseValue)) {
                responseValue = responseValue.replaceAll("
", ""); apiMethodDoc.setResponseUsage(JsonUtil.toPrettyFormat(responseValue)); } else { apiMethodDoc.setResponseUsage(JsonBuildHelper.buildReturnJson(docJavaMethod, projectBuilder)); } // build response params List responseParams = buildReturnApiParams(docJavaMethod, projectBuilder); if (paramsDataToTree) { responseParams = ApiParamTreeUtil.apiParamToTree(responseParams); } apiMethodDoc.setReturnSchema(docJavaMethod.getReturnSchema()); apiMethodDoc.setRequestSchema(docJavaMethod.getRequestSchema()); apiMethodDoc.setResponseParams(responseParams); TornaUtil.setTornaArrayTags(docJavaMethod.getJavaMethod(), apiMethodDoc, apiConfig); methodDocList.add(apiMethodDoc); } return methodDocList; } default ApiMethodReqParam requestParams(final DocJavaMethod docJavaMethod, ProjectDocConfigBuilder builder, List configApiReqParams, FrameworkAnnotations frameworkAnnotations) { JavaMethod javaMethod = docJavaMethod.getJavaMethod(); boolean isStrict = builder.getApiConfig().isStrict(); String className = javaMethod.getDeclaringClass().getCanonicalName(); Map paramTagMap = docJavaMethod.getParamTagMap(); Map paramsComments = docJavaMethod.getParamsComments(); List paramList = new ArrayList<>(); Map mappingParams = new HashMap<>(); List methodAnnotations = javaMethod.getAnnotations(); Map mappingAnnotationMap = frameworkAnnotations.getMappingAnnotations(); for (JavaAnnotation annotation : methodAnnotations) { String annotationName = annotation.getType().getName(); MappingAnnotation mappingAnnotation = mappingAnnotationMap.get(annotationName); if (Objects.nonNull(mappingAnnotation) && StringUtil.isNotEmpty(mappingAnnotation.getParamsProp())) { Object paramsObjects = annotation.getNamedParameter(mappingAnnotation.getParamsProp()); if (Objects.isNull(paramsObjects)) { continue; } String params = StringUtil.removeQuotes(paramsObjects.toString()); if (!params.startsWith("[")) { mappingParamToApiParam(paramsObjects.toString(), paramList, mappingParams); continue; } List headers = (LinkedList) paramsObjects; for (String str : headers) { mappingParamToApiParam(str, paramList, mappingParams); } } } final Map> collect = configApiReqParams.stream().collect(Collectors.groupingBy(ApiReqParam::getParamIn, Collectors.toMap(ApiReqParam::getName, m -> m, (k1, k2) -> k1))); final Map pathReqParamMap = collect.getOrDefault(ApiReqParamInTypeEnum.PATH.getValue(), Collections.emptyMap()); final Map queryReqParamMap = collect.getOrDefault(ApiReqParamInTypeEnum.QUERY.getValue(), Collections.emptyMap()); List parameterList = getJavaParameterList(builder, docJavaMethod, frameworkAnnotations); if (parameterList.isEmpty()) { AtomicInteger querySize = new AtomicInteger(paramList.size() + 1); paramList.addAll(queryReqParamMap.values().stream() .map(p -> ApiReqParam.convertToApiParam(p).setQueryParam(true).setId(querySize.getAndIncrement())) .collect(Collectors.toList())); AtomicInteger pathSize = new AtomicInteger(1); return ApiMethodReqParam.builder() .setPathParams(new ArrayList<>(pathReqParamMap.values().stream() .map(p -> ApiReqParam.convertToApiParam(p).setPathParam(true).setId(pathSize.getAndIncrement())) .collect(Collectors.toList()))) .setQueryParams(paramList) .setRequestParams(new ArrayList<>(0)); } boolean requestFieldToUnderline = builder.getApiConfig().isRequestFieldToUnderline(); int requestBodyCounter = 0; out: for (DocJavaParameter apiParameter : parameterList) { JavaParameter parameter = apiParameter.getJavaParameter(); String paramName = parameter.getName(); if (mappingParams.containsKey(paramName)) { continue; } String typeName = apiParameter.getGenericCanonicalName(); String simpleTypeName = apiParameter.getTypeValue(); String simpleName = simpleTypeName.toLowerCase(); String fullTypeName = apiParameter.getFullyQualifiedName(); if (!paramTagMap.containsKey(paramName) && JavaClassValidateUtil.isPrimitive(fullTypeName) && isStrict) { throw new RuntimeException("ERROR: Unable to find javadoc @param for actual param \"" + paramName + "\" in method " + javaMethod.getName() + " from " + className); } StringBuilder comment = new StringBuilder(this.paramCommentResolve(paramTagMap.get(paramName))); JavaClass javaClass = builder.getJavaProjectBuilder().getClassByName(fullTypeName); String mockValue = JavaFieldUtil.createMockValue(paramsComments, paramName, typeName, simpleTypeName); List annotations = parameter.getAnnotations(); Set groupClasses = JavaClassUtil.getParamGroupJavaClass(annotations, builder.getJavaProjectBuilder()); String strRequired = "false"; boolean isPathVariable = false; boolean isRequestBody = false; boolean required = false; for (JavaAnnotation annotation : annotations) { String annotationName = annotation.getType().getValue(); if (ignoreMvcParamWithAnnotation(annotationName)) { continue out; } if (frameworkAnnotations.getRequestParamAnnotation().getAnnotationName().equals(annotationName) || frameworkAnnotations.getPathVariableAnnotation().getAnnotationName().equals(annotationName)) { String defaultValueProp = DocAnnotationConstants.DEFAULT_VALUE_PROP; String requiredProp = DocAnnotationConstants.REQUIRED_PROP; if (frameworkAnnotations.getRequestParamAnnotation().getAnnotationName().equals(annotationName)) { defaultValueProp = frameworkAnnotations.getRequestParamAnnotation().getDefaultValueProp(); requiredProp = frameworkAnnotations.getRequestParamAnnotation().getRequiredProp(); } if (frameworkAnnotations.getPathVariableAnnotation().getAnnotationName().equals(annotationName)) { defaultValueProp = frameworkAnnotations.getPathVariableAnnotation().getDefaultValueProp(); requiredProp = frameworkAnnotations.getPathVariableAnnotation().getRequiredProp(); isPathVariable = true; } AnnotationValue annotationDefaultVal = annotation.getProperty(defaultValueProp); if (Objects.nonNull(annotationDefaultVal)) { mockValue = DocUtil.resolveAnnotationValue(annotationDefaultVal); } paramName = getParamName(paramName, annotation); AnnotationValue annotationRequired = annotation.getProperty(requiredProp); if (Objects.nonNull(annotationRequired)) { strRequired = annotationRequired.toString(); } else { strRequired = "true"; } } if (JavaClassValidateUtil.isJSR303Required(annotationName)) { strRequired = "true"; } if (frameworkAnnotations.getRequestBodyAnnotation().getAnnotationName().equals(annotationName)) { // if (requestBodyCounter > 0) { // throw new RuntimeException("You have use @RequestBody Passing multiple variables for method " // + javaMethod.getName() + " in " + className + ",@RequestBody annotation could only bind one variables."); // } mockValue = JsonBuildHelper.buildJson(fullTypeName, typeName, Boolean.FALSE, 0, new HashMap<>(), groupClasses, builder); requestBodyCounter++; isRequestBody = true; } required = Boolean.parseBoolean(strRequired); } comment.append(JavaFieldUtil.getJsrComment(annotations)); if (requestFieldToUnderline && !isPathVariable) { paramName = StringUtil.camelToUnderline(paramName); } // file upload if (JavaClassValidateUtil.isFile(typeName)) { ApiParam param = ApiParam.of().setField(paramName).setType(DocGlobalConstants.PARAM_TYPE_FILE) .setId(paramList.size() + 1).setQueryParam(true) .setRequired(required).setVersion(DocGlobalConstants.DEFAULT_VERSION) .setDesc(comment.toString()); if (typeName.contains("[]") || typeName.endsWith(">")) { comment.append("(array of file)"); param.setType(DocGlobalConstants.PARAM_TYPE_FILE); param.setDesc(comment.toString()); param.setHasItems(true); } paramList.add(param); continue; } boolean queryParam = !isRequestBody && !isPathVariable; if (JavaClassValidateUtil.isCollection(fullTypeName) || JavaClassValidateUtil.isArray(fullTypeName)) { String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName); String gicName = gicNameArr[0]; if (JavaClassValidateUtil.isArray(gicName)) { gicName = gicName.substring(0, gicName.indexOf("[")); } // handle array and list mock value mockValue = JavaFieldUtil.createMockValue(paramsComments, paramName, gicName, gicName); if (StringUtil.isNotEmpty(mockValue) && !mockValue.contains(",")) { mockValue = StringUtils.join(mockValue, ",", JavaFieldUtil.createMockValue(paramsComments, paramName, gicName, gicName)); } JavaClass gicJavaClass = builder.getJavaProjectBuilder().getClassByName(gicName); if (gicJavaClass.isEnum()) { Object value = JavaClassUtil.getEnumValue(gicJavaClass, Boolean.TRUE); ApiParam param = ApiParam.of().setField(paramName).setDesc(comment + ",[array of enum]") .setRequired(required) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setId(paramList.size() + 1) .setEnumValues(JavaClassUtil.getEnumValues(gicJavaClass)) .setEnumInfo(JavaClassUtil.getEnumInfo(gicJavaClass, builder)) .setType("array").setValue(String.valueOf(value)); paramList.add(param); if (requestBodyCounter > 0) { Map map = OpenApiSchemaUtil.arrayTypeSchema(gicName); docJavaMethod.setRequestSchema(map); } } else if (JavaClassValidateUtil.isPrimitive(gicName)) { String shortSimple = DocClassUtil.processTypeNameForParams(gicName); ApiParam param = ApiParam.of() .setField(paramName) .setDesc(comment + ",[array of " + shortSimple + "]") .setRequired(required) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setId(paramList.size() + 1) .setType("array") .setVersion(DocGlobalConstants.DEFAULT_VERSION) .setValue(mockValue); paramList.add(param); if (requestBodyCounter > 0) { Map map = OpenApiSchemaUtil.arrayTypeSchema(gicName); docJavaMethod.setRequestSchema(map); } } else if (JavaClassValidateUtil.isFile(gicName)) { // file upload ApiParam param = ApiParam.of().setField(paramName) .setType(DocGlobalConstants.PARAM_TYPE_FILE) .setId(paramList.size() + 1) .setQueryParam(true) .setRequired(required) .setVersion(DocGlobalConstants.DEFAULT_VERSION) .setHasItems(true) .setDesc(comment + "(array of file)"); paramList.add(param); } else { if (requestBodyCounter > 0) { // for json paramList.addAll(ParamsBuildHelper.buildParams(gicNameArr[0], DocGlobalConstants.EMPTY, 0, String.valueOf(required), Boolean.FALSE, new HashMap<>(), builder, groupClasses, 0, Boolean.TRUE, null)); } } } else if (JavaClassValidateUtil.isPrimitive(fullTypeName)) { ApiParam param = ApiParam.of() .setField(paramName) .setType(DocClassUtil.processTypeNameForParams(simpleName)) .setId(paramList.size() + 1) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setValue(mockValue) .setDesc(comment.toString()) .setRequired(required) .setVersion(DocGlobalConstants.DEFAULT_VERSION); paramList.add(param); if (requestBodyCounter > 0) { Map map = OpenApiSchemaUtil.primaryTypeSchema(simpleName); docJavaMethod.setRequestSchema(map); } } else if (JavaClassValidateUtil.isMap(fullTypeName)) { log.warning("When using smart-doc, it is not recommended to use Map to receive parameters, Check it in " + javaMethod.getDeclaringClass().getCanonicalName() + "#" + javaMethod.getName()); // is map without Gic if (JavaClassValidateUtil.isMap(typeName)) { ApiParam apiParam = ApiParam.of() .setField(paramName) .setType("map") .setId(paramList.size() + 1) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setDesc(comment.toString()) .setRequired(required) .setVersion(DocGlobalConstants.DEFAULT_VERSION); paramList.add(apiParam); if (requestBodyCounter > 0) { Map map = OpenApiSchemaUtil.mapTypeSchema("object"); docJavaMethod.setRequestSchema(map); } continue; } String[] gicNameArr = DocClassUtil.getSimpleGicName(typeName); if (JavaClassValidateUtil.isPrimitive(gicNameArr[1])) { ApiParam apiParam = ApiParam.of() .setField(paramName) .setType("map") .setId(paramList.size() + 1) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setDesc(comment.toString()) .setRequired(required) .setVersion(DocGlobalConstants.DEFAULT_VERSION); paramList.add(apiParam); if (requestBodyCounter > 0) { Map map = OpenApiSchemaUtil.mapTypeSchema(gicNameArr[1]); docJavaMethod.setRequestSchema(map); } } else { paramList.addAll(ParamsBuildHelper.buildParams(gicNameArr[1], DocGlobalConstants.EMPTY, 0, String.valueOf(required), Boolean.FALSE, new HashMap<>(), builder, groupClasses, 0, Boolean.FALSE, null)); } } // param is enum else if (javaClass.isEnum()) { String o = JavaClassUtil.getEnumParams(javaClass); Object value = JavaClassUtil.getEnumValue(javaClass, isPathVariable || queryParam); ApiParam param = ApiParam.of().setField(paramName) .setId(paramList.size() + 1) .setPathParam(isPathVariable) .setQueryParam(queryParam) .setValue(String.valueOf(value)) .setType("enum").setDesc(StringUtil.removeQuotes(o)) .setRequired(required) .setVersion(DocGlobalConstants.DEFAULT_VERSION) .setEnumInfo(JavaClassUtil.getEnumInfo(javaClass, builder)) .setEnumValues(JavaClassUtil.getEnumValues(javaClass)); paramList.add(param); } else { paramList.addAll(ParamsBuildHelper.buildParams(typeName, DocGlobalConstants.EMPTY, 0, String.valueOf(required), Boolean.FALSE, new HashMap<>(), builder, groupClasses, 0, Boolean.FALSE, null)); } } return ApiParamTreeUtil.buildMethodReqParam(paramList, queryReqParamMap, pathReqParamMap, requestBodyCounter); } default ApiRequestExample buildReqJson(DocJavaMethod javaMethod, ApiMethodDoc apiMethodDoc, String methodType, ProjectDocConfigBuilder configBuilder, FrameworkAnnotations frameworkAnnotations) { JavaMethod method = javaMethod.getJavaMethod(); Map pathParamsMap = new LinkedHashMap<>(); Map queryParamsMap = new LinkedHashMap<>(); apiMethodDoc.getPathParams().stream().filter(Objects::nonNull).filter(p -> StringUtil.isNotEmpty(p.getValue()) || p.isConfigParam()) .forEach(param -> pathParamsMap.put(param.getSourceField(), param.getValue())); apiMethodDoc.getQueryParams().stream().filter(Objects::nonNull).filter(p -> StringUtil.isNotEmpty(p.getValue()) || p.isConfigParam()) .forEach(param -> queryParamsMap.put(param.getSourceField(), param.getValue())); List methodAnnotations = method.getAnnotations(); Map mappingAnnotationMap = frameworkAnnotations.getMappingAnnotations(); for (JavaAnnotation annotation : methodAnnotations) { String annotationName = annotation.getType().getName(); MappingAnnotation mappingAnnotation = mappingAnnotationMap.get(annotationName); if (Objects.nonNull(mappingAnnotation) && StringUtil.isNotEmpty(mappingAnnotation.getParamsProp())) { Object paramsObjects = annotation.getNamedParameter(mappingAnnotation.getParamsProp()); if (Objects.isNull(paramsObjects)) { continue; } String params = StringUtil.removeQuotes(paramsObjects.toString()); if (!params.startsWith("[")) { mappingParamProcess(paramsObjects.toString(), queryParamsMap); continue; } List headers = (LinkedList) paramsObjects; for (String str : headers) { mappingParamProcess(str, queryParamsMap); } } } List parameterList = getJavaParameterList(configBuilder, javaMethod, frameworkAnnotations); List reqHeaderList = apiMethodDoc.getRequestHeaders(); if (parameterList.size() < 1) { String path = apiMethodDoc.getPath().split(";")[0]; path = DocUtil.formatAndRemove(path, pathParamsMap); String url = UrlUtil.urlJoin(path, queryParamsMap); url = StringUtil.removeQuotes(url); url = apiMethodDoc.getServerUrl() + "/" + url; url = UrlUtil.simplifyUrl(url); CurlRequest curlRequest = CurlRequest.builder() .setContentType(apiMethodDoc.getContentType()) .setType(methodType) .setReqHeaders(reqHeaderList) .setUrl(url); String format = CurlUtil.toCurl(curlRequest); return ApiRequestExample.builder().setUrl(apiMethodDoc.getUrl()).setExampleBody(format); } boolean requestFieldToUnderline = configBuilder.getApiConfig().isRequestFieldToUnderline(); Map paramsComments = DocUtil.getCommentsByTag(method, DocTags.PARAM, null); List mvcRequestAnnotations = this.listMvcRequestAnnotations(); List formDataList = new ArrayList<>(); ApiRequestExample requestExample = ApiRequestExample.builder(); out: for (DocJavaParameter apiParameter : parameterList) { JavaParameter parameter = apiParameter.getJavaParameter(); String paramName = parameter.getName(); String typeName = apiParameter.getFullyQualifiedName(); String gicTypeName = apiParameter.getGenericCanonicalName(); String simpleTypeName = apiParameter.getTypeValue(); JavaClass javaClass = configBuilder.getJavaProjectBuilder().getClassByName(typeName); String[] globGicName = DocClassUtil.getSimpleGicName(gicTypeName); String comment = this.paramCommentResolve(paramsComments.get(paramName)); String mockValue = JavaFieldUtil.createMockValue(paramsComments, paramName, gicTypeName, simpleTypeName); if (queryParamsMap.containsKey(paramName)) { mockValue = queryParamsMap.get(paramName); } if (requestFieldToUnderline) { paramName = StringUtil.camelToUnderline(paramName); } List annotations = parameter.getAnnotations(); Set groupClasses = JavaClassUtil.getParamGroupJavaClass(annotations, configBuilder.getJavaProjectBuilder()); boolean paramAdded = false; boolean requestParam = false; for (JavaAnnotation annotation : annotations) { String annotationName = annotation.getType().getValue(); String fullName = annotation.getType().getSimpleName(); if (!mvcRequestAnnotations.contains(fullName) || paramAdded) { continue; } if (ignoreMvcParamWithAnnotation(annotationName)) { continue out; } AnnotationValue annotationDefaultVal = annotation.getProperty(DocAnnotationConstants.DEFAULT_VALUE_PROP); if (Objects.nonNull(annotationDefaultVal)) { mockValue = DocUtil.resolveAnnotationValue(annotationDefaultVal); } paramName = getParamName(paramName, annotation); if (frameworkAnnotations.getRequestBodyAnnotation().getAnnotationName().equals(annotationName)) { // priority use mapping annotation's consumer value if (apiMethodDoc.getContentType().equals(DocGlobalConstants.URL_CONTENT_TYPE)) { apiMethodDoc.setContentType(JSON_CONTENT_TYPE); } boolean isArrayOrCollection = false; if (JavaClassValidateUtil.isArray(typeName) || JavaClassValidateUtil.isCollection(typeName)) { simpleTypeName = globGicName[0]; isArrayOrCollection = true; } if (JavaClassValidateUtil.isPrimitive(simpleTypeName)) { if (isArrayOrCollection) { if (StringUtil.isNotEmpty(mockValue)) { mockValue = "[" + mockValue + "]"; } else { mockValue = "[" + DocUtil.getValByTypeAndFieldName(simpleTypeName, paramName) + "]"; } mockValue = JsonUtil.toPrettyFormat(mockValue); } requestExample.setJsonBody(mockValue).setJson(true); } else { String json = JsonBuildHelper.buildJson(typeName, gicTypeName, Boolean.FALSE, 0, new HashMap<>(), groupClasses, configBuilder); requestExample.setJsonBody(JsonUtil.toPrettyFormat(json)).setJson(true); } queryParamsMap.remove(paramName); paramAdded = true; } else if (frameworkAnnotations.getPathVariableAnnotation().getAnnotationName().contains(annotationName)) { if (javaClass.isEnum()) { Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE); mockValue = StringUtil.removeQuotes(String.valueOf(value)); } if (pathParamsMap.containsKey(paramName)) { mockValue = pathParamsMap.get(paramName); } pathParamsMap.put(paramName, mockValue); paramAdded = true; } else if (frameworkAnnotations.getRequestParamAnnotation().getAnnotationName().contains(annotationName)) { if (javaClass.isEnum()) { Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE); mockValue = StringUtil.removeQuotes(String.valueOf(value)); } if (queryParamsMap.containsKey(paramName)) { mockValue = queryParamsMap.get(paramName); } if (JavaClassValidateUtil.isPrimitive(simpleTypeName)) { requestExample.addJsonBody(mockValue); } if (JavaClassValidateUtil.isFile(typeName)) { break; } // array and list queryParamsMap.put(paramName, mockValue); requestParam = true; paramAdded = true; } } if (paramAdded) { continue; } // file upload if (JavaClassValidateUtil.isFile(gicTypeName)) { apiMethodDoc.setContentType(FILE_CONTENT_TYPE); FormData formData = new FormData(); formData.setKey(paramName); formData.setType("file"); if (typeName.contains("[]") || typeName.endsWith(">")) { comment = comment + "(array of file)"; formData.setType(DocGlobalConstants.PARAM_TYPE_FILE); formData.setHasItems(true); } formData.setDescription(comment); formData.setValue(mockValue); formData.setSrc(new ArrayList(0)); formDataList.add(formData); } else if (JavaClassValidateUtil.isPrimitive(typeName) && !requestParam) { FormData formData = new FormData(); formData.setKey(paramName); formData.setDescription(comment); formData.setType("text"); formData.setValue(mockValue); formDataList.add(formData); } else if (JavaClassValidateUtil.isArray(typeName) || JavaClassValidateUtil.isCollection(typeName)) { String gicName = globGicName[0]; if (JavaClassValidateUtil.isArray(gicName)) { gicName = gicName.substring(0, gicName.indexOf("[")); } if (!JavaClassValidateUtil.isPrimitive(gicName) && !configBuilder.getJavaProjectBuilder().getClassByName(gicName).isEnum()) { throw new RuntimeException("can't support binding Collection on method " + method.getName() + "Check it in " + method.getDeclaringClass().getCanonicalName()); } String value; JavaClass javaClass1 = configBuilder.getClassByName(gicName); if (Objects.nonNull(javaClass1) && javaClass1.isEnum()) { value = String.valueOf(JavaClassUtil.getEnumValue(javaClass1, Boolean.TRUE)); } else { value = RandomUtil.randomValueByType(gicName); } FormData formData = new FormData(); formData.setKey(paramName); if (!paramName.contains("[]")) { formData.setKey(paramName + "[]"); } formData.setDescription(comment); formData.setType("text"); formData.setValue(value); formDataList.add(formData); } else if (javaClass.isEnum()) { // do nothing Object value = JavaClassUtil.getEnumValue(javaClass, Boolean.TRUE); String strVal = StringUtil.removeQuotes(String.valueOf(value)); FormData formData = new FormData(); formData.setKey(paramName); formData.setType("text"); formData.setDescription(comment); formData.setValue(strVal); formDataList.add(formData); } else { formDataList.addAll(FormDataBuildHelper.getFormData(gicTypeName, new HashMap<>(), 0, configBuilder, DocGlobalConstants.EMPTY)); } } // set content-type to fromData boolean hasFormDataUploadFile = formDataList.stream().anyMatch(form -> Objects.equals(form.getType(), DocGlobalConstants.PARAM_TYPE_FILE)); Map> formDataGroupMap = formDataList.stream() .collect(Collectors.groupingBy(e -> Objects.equals(e.getType(), DocGlobalConstants.PARAM_TYPE_FILE))); List fileFormDataList = formDataGroupMap.getOrDefault(Boolean.TRUE, new ArrayList<>()); if (hasFormDataUploadFile) { apiMethodDoc.setContentType(FILE_CONTENT_TYPE); } requestExample.setFormDataList(formDataList); String[] paths = apiMethodDoc.getPath().split(";"); String path = paths[0]; String body; String exampleBody; String url; // curl send file to convert final Map formDataToMap = DocUtil.formDataToMap(formDataList); // formData add to params '--data' queryParamsMap.putAll(formDataToMap); if (Methods.POST.getValue().equals(methodType) || Methods.PUT.getValue().equals(methodType)) { // for post put path = DocUtil.formatAndRemove(path, pathParamsMap); body = UrlUtil.urlJoin(DocGlobalConstants.EMPTY, queryParamsMap) .replace("?", DocGlobalConstants.EMPTY); body = StringUtil.removeQuotes(body); url = apiMethodDoc.getServerUrl() + "/" + path; url = UrlUtil.simplifyUrl(url); if (requestExample.isJson()) { if (StringUtil.isNotEmpty(body)) { url = url + "?" + body; } CurlRequest curlRequest = CurlRequest.builder() .setBody(requestExample.getJsonBody()) .setContentType(apiMethodDoc.getContentType()) .setType(methodType) .setReqHeaders(reqHeaderList) .setUrl(url); exampleBody = CurlUtil.toCurl(curlRequest); } else { CurlRequest curlRequest; if (StringUtil.isNotEmpty(body)) { curlRequest = CurlRequest.builder() .setBody(body) .setContentType(apiMethodDoc.getContentType()) .setFileFormDataList(fileFormDataList) .setType(methodType) .setReqHeaders(reqHeaderList) .setUrl(url); } else { curlRequest = CurlRequest.builder() .setBody(requestExample.getJsonBody()) .setContentType(apiMethodDoc.getContentType()) .setFileFormDataList(fileFormDataList) .setType(methodType) .setReqHeaders(reqHeaderList) .setUrl(url); } exampleBody = CurlUtil.toCurl(curlRequest); } requestExample.setExampleBody(exampleBody).setUrl(url); } else { // for get delete url = formatRequestUrl(pathParamsMap, queryParamsMap, apiMethodDoc.getServerUrl(), path); CurlRequest curlRequest = CurlRequest.builder() .setBody(requestExample.getJsonBody()) .setContentType(apiMethodDoc.getContentType()) .setType(methodType) .setReqHeaders(reqHeaderList) .setUrl(url); exampleBody = CurlUtil.toCurl(curlRequest); requestExample.setExampleBody(exampleBody) .setJsonBody(requestExample.isJson() ? requestExample.getJsonBody() : DocGlobalConstants.EMPTY) .setUrl(url); } return requestExample; } default boolean defaultEntryPoint(JavaClass cls, FrameworkAnnotations frameworkAnnotations) { if (cls.isAnnotation() || cls.isEnum()) { return false; } if (Objects.isNull(frameworkAnnotations)) { return false; } List classAnnotations = DocClassUtil.getAnnotations(cls); Map entryAnnotationMap = frameworkAnnotations.getEntryAnnotations(); return classAnnotations.stream().anyMatch(annotation -> { String name = annotation.getType().getValue(); return entryAnnotationMap.containsKey(name); }); } default List getParentsClassMethods(ApiConfig apiConfig, ProjectDocConfigBuilder projectBuilder, JavaClass cls) { List docJavaMethods = new ArrayList<>(); JavaClass parentClass = cls.getSuperJavaClass(); if (Objects.nonNull(parentClass) && !"Object".equals(parentClass.getSimpleName())) { Map actualTypesMap = JavaClassUtil.getActualTypesMap(parentClass); List parentMethodList = parentClass.getMethods(); for (JavaMethod method : parentMethodList) { docJavaMethods.add(convertToDocJavaMethod(apiConfig, projectBuilder, method, actualTypesMap)); } docJavaMethods.addAll(getParentsClassMethods(apiConfig, projectBuilder, parentClass)); } return docJavaMethods; } default DocJavaMethod convertToDocJavaMethod(ApiConfig apiConfig, ProjectDocConfigBuilder projectBuilder, JavaMethod method, Map actualTypesMap) { JavaClass cls = method.getDeclaringClass(); String clzName = cls.getCanonicalName(); if (StringUtil.isEmpty(method.getComment()) && apiConfig.isStrict()) { throw new RuntimeException("Unable to find comment for method " + method.getName() + " in " + cls.getCanonicalName()); } String classAuthor = JavaClassUtil.getClassTagsValue(cls, DocTags.AUTHOR, Boolean.TRUE); DocJavaMethod docJavaMethod = DocJavaMethod.builder().setJavaMethod(method).setActualTypesMap(actualTypesMap); if (Objects.nonNull(method.getTagByName(DocTags.DOWNLOAD))) { docJavaMethod.setDownload(true); } DocletTag pageTag = method.getTagByName(DocTags.PAGE); if (Objects.nonNull(method.getTagByName(DocTags.PAGE))) { String pageUrl = projectBuilder.getServerUrl() + "/" + pageTag.getValue(); docJavaMethod.setPage(UrlUtil.simplifyUrl(pageUrl)); } DocletTag docletTag = method.getTagByName(DocTags.GROUP); if (Objects.nonNull(docletTag)) { docJavaMethod.setGroup(docletTag.getValue()); } docJavaMethod.setParamTagMap(DocUtil.getCommentsByTag(method, DocTags.PARAM, clzName)); docJavaMethod.setParamsComments(DocUtil.getCommentsByTag(method, DocTags.PARAM, null)); Map authorMap = DocUtil.getCommentsByTag(method, DocTags.AUTHOR, cls.getName()); String authorValue = String.join(", ", new ArrayList<>(authorMap.keySet())); if (apiConfig.isShowAuthor() && StringUtil.isNotEmpty(authorValue)) { docJavaMethod.setAuthor(JsonUtil.toPrettyFormat(authorValue)); } if (apiConfig.isShowAuthor() && StringUtil.isEmpty(authorValue)) { docJavaMethod.setAuthor(classAuthor); } String comment = DocUtil.getEscapeAndCleanComment(method.getComment()); docJavaMethod.setDesc(comment); String version = DocUtil.getNormalTagComments(method, DocTags.SINCE, cls.getName()); docJavaMethod.setVersion(version); String apiNoteValue = DocUtil.getNormalTagComments(method, DocTags.API_NOTE, cls.getName()); if (StringUtil.isEmpty(apiNoteValue)) { apiNoteValue = method.getComment(); } docJavaMethod.setDetail(apiNoteValue != null ? apiNoteValue : ""); return docJavaMethod; } boolean isEntryPoint(JavaClass javaClass, FrameworkAnnotations frameworkAnnotations); List listMvcRequestAnnotations(); void requestMappingPostProcess(JavaClass javaClass, JavaMethod method, RequestMapping requestMapping); boolean ignoreMvcParamWithAnnotation(String annotation); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy