Search in sources :

Example 1 with JavadocProvider

use of org.springdoc.core.providers.JavadocProvider in project springdoc-openapi by springdoc.

the class AbstractOpenApiResource method calculatePath.

/**
 * Calculate path.
 *
 * @param handlerMethod the handler method
 * @param routerOperation the router operation
 * @param locale the locale
 */
protected void calculatePath(HandlerMethod handlerMethod, RouterOperation routerOperation, Locale locale) {
    String operationPath = routerOperation.getPath();
    Set<RequestMethod> requestMethods = new HashSet<>(Arrays.asList(routerOperation.getMethods()));
    io.swagger.v3.oas.annotations.Operation apiOperation = routerOperation.getOperation();
    String[] methodConsumes = routerOperation.getConsumes();
    String[] methodProduces = routerOperation.getProduces();
    String[] headers = routerOperation.getHeaders();
    Map<String, String> queryParams = routerOperation.getQueryParams();
    OpenAPI openAPI = openAPIService.getCalculatedOpenAPI();
    Components components = openAPI.getComponents();
    Paths paths = openAPI.getPaths();
    Map<HttpMethod, Operation> operationMap = null;
    if (paths.containsKey(operationPath)) {
        PathItem pathItem = paths.get(operationPath);
        operationMap = pathItem.readOperationsMap();
    }
    JavadocProvider javadocProvider = operationParser.getJavadocProvider();
    for (RequestMethod requestMethod : requestMethods) {
        Operation existingOperation = getExistingOperation(operationMap, requestMethod);
        Method method = handlerMethod.getMethod();
        // skip hidden operations
        if (operationParser.isHidden(method))
            continue;
        RequestMapping reqMappingClass = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), RequestMapping.class);
        MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces, headers, locale);
        methodAttributes.setMethodOverloaded(existingOperation != null);
        // Use the javadoc return if present
        if (javadocProvider != null) {
            methodAttributes.setJavadocReturn(javadocProvider.getMethodJavadocReturn(handlerMethod.getMethod()));
        }
        if (reqMappingClass != null) {
            methodAttributes.setClassConsumes(reqMappingClass.consumes());
            methodAttributes.setClassProduces(reqMappingClass.produces());
        }
        methodAttributes.calculateHeadersForClass(method.getDeclaringClass());
        methodAttributes.calculateConsumesProduces(method);
        Operation operation = (existingOperation != null) ? existingOperation : new Operation();
        if (isDeprecated(method))
            operation.setDeprecated(true);
        // Add documentation from operation annotation
        if (apiOperation == null || StringUtils.isBlank(apiOperation.operationId()))
            apiOperation = AnnotatedElementUtils.findMergedAnnotation(method, io.swagger.v3.oas.annotations.Operation.class);
        calculateJsonView(apiOperation, methodAttributes, method);
        if (apiOperation != null)
            openAPI = operationParser.parse(apiOperation, operation, openAPI, methodAttributes);
        fillParametersList(operation, queryParams, methodAttributes);
        // compute tags
        operation = openAPIService.buildTags(handlerMethod, operation, openAPI, locale);
        io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc = AnnotatedElementUtils.findMergedAnnotation(method, io.swagger.v3.oas.annotations.parameters.RequestBody.class);
        // RequestBody in Operation
        requestBuilder.getRequestBodyBuilder().buildRequestBodyFromDoc(requestBodyDoc, methodAttributes, components, methodAttributes.getJsonViewAnnotationForRequestBody()).ifPresent(operation::setRequestBody);
        // requests
        operation = requestBuilder.build(handlerMethod, requestMethod, operation, methodAttributes, openAPI);
        // responses
        ApiResponses apiResponses = responseBuilder.build(components, handlerMethod, operation, methodAttributes);
        operation.setResponses(apiResponses);
        // get javadoc method description
        if (javadocProvider != null) {
            String description = javadocProvider.getMethodJavadocDescription(handlerMethod.getMethod());
            if (!StringUtils.isEmpty(description) && StringUtils.isEmpty(operation.getDescription()))
                operation.setDescription(description);
        }
        Set<io.swagger.v3.oas.annotations.callbacks.Callback> apiCallbacks = AnnotatedElementUtils.findMergedRepeatableAnnotations(method, io.swagger.v3.oas.annotations.callbacks.Callback.class);
        // callbacks
        buildCallbacks(openAPI, methodAttributes, operation, apiCallbacks);
        // allow for customisation
        operation = customiseOperation(operation, handlerMethod);
        PathItem pathItemObject = buildPathItem(requestMethod, operation, operationPath, paths);
        paths.addPathItem(operationPath, pathItemObject);
    }
}
Also used : RequestMethod(org.springframework.web.bind.annotation.RequestMethod) JavadocProvider(org.springdoc.core.providers.JavadocProvider) Operation(io.swagger.v3.oas.models.Operation) RouterOperation(org.springdoc.core.fn.RouterOperation) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) Components(io.swagger.v3.oas.models.Components) PathItem(io.swagger.v3.oas.models.PathItem) Paths(io.swagger.v3.oas.models.Paths) ApiResponses(io.swagger.v3.oas.models.responses.ApiResponses) HashSet(java.util.HashSet) HandlerMethod(org.springframework.web.method.HandlerMethod) Method(java.lang.reflect.Method) RequestMethod(org.springframework.web.bind.annotation.RequestMethod) HttpMethod(io.swagger.v3.oas.models.PathItem.HttpMethod) Callback(io.swagger.v3.oas.annotations.callbacks.Callback) OpenAPI(io.swagger.v3.oas.models.OpenAPI) HttpMethod(io.swagger.v3.oas.models.PathItem.HttpMethod) MethodAttributes(org.springdoc.core.MethodAttributes)

Example 2 with JavadocProvider

use of org.springdoc.core.providers.JavadocProvider in project springdoc-openapi by springdoc.

the class AbstractRequestService method build.

/**
 * Build operation.
 *
 * @param handlerMethod the handler method
 * @param requestMethod the request method
 * @param operation the operation
 * @param methodAttributes the method attributes
 * @param openAPI the open api
 * @return the operation
 */
public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod, Operation operation, MethodAttributes methodAttributes, OpenAPI openAPI) {
    // Documentation
    String operationId = operationService.getOperationId(handlerMethod.getMethod().getName(), operation.getOperationId(), openAPI);
    operation.setOperationId(operationId);
    // requests
    String[] pNames = this.localSpringDocParameterNameDiscoverer.getParameterNames(handlerMethod.getMethod());
    MethodParameter[] parameters = handlerMethod.getMethodParameters();
    String[] reflectionParametersNames = Arrays.stream(handlerMethod.getMethod().getParameters()).map(java.lang.reflect.Parameter::getName).toArray(String[]::new);
    if (pNames == null || Arrays.stream(pNames).anyMatch(Objects::isNull))
        pNames = reflectionParametersNames;
    parameters = DelegatingMethodParameter.customize(pNames, parameters, parameterBuilder.getDelegatingMethodParameterCustomizer());
    RequestBodyInfo requestBodyInfo = new RequestBodyInfo();
    List<Parameter> operationParameters = (operation.getParameters() != null) ? operation.getParameters() : new ArrayList<>();
    Map<String, io.swagger.v3.oas.annotations.Parameter> parametersDocMap = getApiParameters(handlerMethod.getMethod());
    Components components = openAPI.getComponents();
    JavadocProvider javadocProvider = operationService.getJavadocProvider();
    for (MethodParameter methodParameter : parameters) {
        // check if query param
        Parameter parameter;
        io.swagger.v3.oas.annotations.Parameter parameterDoc = AnnotatedElementUtils.findMergedAnnotation(AnnotatedElementUtils.forAnnotations(methodParameter.getParameterAnnotations()), io.swagger.v3.oas.annotations.Parameter.class);
        final String pName = methodParameter.getParameterName();
        ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder);
        if (parameterDoc == null)
            parameterDoc = parametersDocMap.get(parameterInfo.getpName());
        // use documentation as reference
        if (parameterDoc != null) {
            if (parameterDoc.hidden() || parameterDoc.schema().hidden())
                continue;
            parameter = parameterBuilder.buildParameterFromDoc(parameterDoc, components, methodAttributes.getJsonViewAnnotation(), methodAttributes.getLocale());
            parameterInfo.setParameterModel(parameter);
        }
        if (!isParamToIgnore(methodParameter)) {
            parameter = buildParams(parameterInfo, components, requestMethod, methodAttributes.getJsonViewAnnotation());
            // Merge with the operation parameters
            parameter = GenericParameterService.mergeParameter(operationParameters, parameter);
            List<Annotation> parameterAnnotations = Arrays.asList(methodParameter.getParameterAnnotations());
            if (isValidParameter(parameter)) {
                // Add param javadoc
                if (StringUtils.isBlank(parameter.getDescription()) && javadocProvider != null) {
                    String paramJavadocDescription = getParamJavadoc(javadocProvider, methodParameter, pName);
                    if (!StringUtils.isBlank(paramJavadocDescription)) {
                        parameter.setDescription(paramJavadocDescription);
                    }
                }
                applyBeanValidatorAnnotations(parameter, parameterAnnotations);
            } else if (!RequestMethod.GET.equals(requestMethod)) {
                if (operation.getRequestBody() != null)
                    requestBodyInfo.setRequestBody(operation.getRequestBody());
                requestBodyService.calculateRequestBodyInfo(components, methodAttributes, parameterInfo, requestBodyInfo);
                // Add requestBody javadoc
                if (StringUtils.isBlank(requestBodyInfo.getRequestBody().getDescription()) && javadocProvider != null) {
                    String paramJavadocDescription = getParamJavadoc(javadocProvider, methodParameter, pName);
                    if (!StringUtils.isBlank(paramJavadocDescription)) {
                        requestBodyInfo.getRequestBody().setDescription(paramJavadocDescription);
                    }
                }
                applyBeanValidatorAnnotations(requestBodyInfo.getRequestBody(), parameterAnnotations, methodParameter.isOptional());
            }
            customiseParameter(parameter, parameterInfo, operationParameters);
        }
    }
    LinkedHashMap<String, Parameter> map = getParameterLinkedHashMap(components, methodAttributes, operationParameters, parametersDocMap);
    setParams(operation, new ArrayList<>(map.values()), requestBodyInfo);
    return operation;
}
Also used : JavadocProvider(org.springdoc.core.providers.JavadocProvider) Annotation(java.lang.annotation.Annotation) SchemaPropertyDeprecatingConverter.containsDeprecatedAnnotation(org.springdoc.core.converters.SchemaPropertyDeprecatingConverter.containsDeprecatedAnnotation) Components(io.swagger.v3.oas.models.Components) Parameter(io.swagger.v3.oas.models.parameters.Parameter) MethodParameter(org.springframework.core.MethodParameter) MethodParameter(org.springframework.core.MethodParameter)

Example 3 with JavadocProvider

use of org.springdoc.core.providers.JavadocProvider in project springdoc-openapi by springdoc.

the class GenericResponseService method buildGenericResponse.

/**
 * Build generic response.
 *
 * @param components the components
 * @param findControllerAdvice the find controller advice
 * @param locale the locale
 */
public void buildGenericResponse(Components components, Map<String, Object> findControllerAdvice, Locale locale) {
    // ControllerAdvice
    for (Map.Entry<String, Object> entry : findControllerAdvice.entrySet()) {
        List<Method> methods = new ArrayList<>();
        Object controllerAdvice = entry.getValue();
        // get all methods with annotation @ExceptionHandler
        Class<?> objClz = controllerAdvice.getClass();
        if (org.springframework.aop.support.AopUtils.isAopProxy(controllerAdvice))
            objClz = org.springframework.aop.support.AopUtils.getTargetClass(controllerAdvice);
        ControllerAdviceInfo controllerAdviceInfo = new ControllerAdviceInfo(controllerAdvice);
        Arrays.stream(ReflectionUtils.getAllDeclaredMethods(objClz)).filter(m -> m.isAnnotationPresent(ExceptionHandler.class) || isResponseEntityExceptionHandlerMethod(m)).forEach(methods::add);
        // for each one build ApiResponse and add it to existing responses
        for (Method method : methods) {
            if (!operationService.isHidden(method)) {
                RequestMapping reqMappingMethod = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
                String[] methodProduces = { springDocConfigProperties.getDefaultProducesMediaType() };
                if (reqMappingMethod != null)
                    methodProduces = reqMappingMethod.produces();
                Map<String, ApiResponse> controllerAdviceInfoApiResponseMap = controllerAdviceInfo.getApiResponseMap();
                MethodParameter methodParameter = new MethodParameter(method, -1);
                ApiResponses apiResponsesOp = new ApiResponses();
                MethodAttributes methodAttributes = new MethodAttributes(methodProduces, springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), controllerAdviceInfoApiResponseMap, locale);
                // calculate JsonView Annotation
                methodAttributes.setJsonViewAnnotation(AnnotatedElementUtils.findMergedAnnotation(method, JsonView.class));
                // use the javadoc return if present
                if (operationService.getJavadocProvider() != null) {
                    JavadocProvider javadocProvider = operationService.getJavadocProvider();
                    methodAttributes.setJavadocReturn(javadocProvider.getMethodJavadocReturn(methodParameter.getMethod()));
                }
                Map<String, ApiResponse> apiResponses = computeResponseFromDoc(components, methodParameter, apiResponsesOp, methodAttributes);
                buildGenericApiResponses(components, methodParameter, apiResponsesOp, methodAttributes);
                apiResponses.forEach(controllerAdviceInfoApiResponseMap::put);
            }
        }
        controllerAdviceInfos.add(controllerAdviceInfo);
    }
}
Also used : AnnotatedElementUtils(org.springframework.core.annotation.AnnotatedElementUtils) ConverterUtils.isResponseTypeWrapper(org.springdoc.core.converters.ConverterUtils.isResponseTypeWrapper) Arrays(java.util.Arrays) JsonView(com.fasterxml.jackson.annotation.JsonView) LoggerFactory(org.slf4j.LoggerFactory) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) ArrayUtils(org.apache.commons.lang3.ArrayUtils) Operation(io.swagger.v3.oas.models.Operation) StringUtils(org.apache.commons.lang3.StringUtils) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) AnnotationsUtils(io.swagger.v3.core.util.AnnotationsUtils) HandlerMethod(org.springframework.web.method.HandlerMethod) JavadocProvider(org.springdoc.core.providers.JavadocProvider) Locale(java.util.Locale) Map(java.util.Map) MethodParameter(org.springframework.core.MethodParameter) ExceptionHandler(org.springframework.web.bind.annotation.ExceptionHandler) Schema(io.swagger.v3.oas.models.media.Schema) ResolvableType(org.springframework.core.ResolvableType) ResponseStatus(org.springframework.web.bind.annotation.ResponseStatus) Method(java.lang.reflect.Method) SpringDocAnnotationsUtils.mergeSchema(org.springdoc.core.SpringDocAnnotationsUtils.mergeSchema) ApiResponses(io.swagger.v3.oas.models.responses.ApiResponses) ControllerAdvice(org.springframework.web.bind.annotation.ControllerAdvice) ApiResponse(io.swagger.v3.oas.models.responses.ApiResponse) SpringDocAnnotationsUtils.getContent(org.springdoc.core.SpringDocAnnotationsUtils.getContent) Content(io.swagger.v3.oas.models.media.Content) Logger(org.slf4j.Logger) Set(java.util.Set) DEFAULT_DESCRIPTION(org.springdoc.core.Constants.DEFAULT_DESCRIPTION) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) HttpStatus(org.springframework.http.HttpStatus) List(java.util.List) Stream(java.util.stream.Stream) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) CollectionUtils(org.springframework.util.CollectionUtils) ReflectionUtils(org.springframework.util.ReflectionUtils) Annotation(java.lang.annotation.Annotation) Components(io.swagger.v3.oas.models.Components) SpringDocAnnotationsUtils.extractSchema(org.springdoc.core.SpringDocAnnotationsUtils.extractSchema) Optional(java.util.Optional) ControllerAdviceBean(org.springframework.web.method.ControllerAdviceBean) ArrayList(java.util.ArrayList) JsonView(com.fasterxml.jackson.annotation.JsonView) JavadocProvider(org.springdoc.core.providers.JavadocProvider) HandlerMethod(org.springframework.web.method.HandlerMethod) Method(java.lang.reflect.Method) ApiResponse(io.swagger.v3.oas.models.responses.ApiResponse) RequestMapping(org.springframework.web.bind.annotation.RequestMapping) ExceptionHandler(org.springframework.web.bind.annotation.ExceptionHandler) MethodParameter(org.springframework.core.MethodParameter) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ApiResponses(io.swagger.v3.oas.models.responses.ApiResponses)

Aggregations

Components (io.swagger.v3.oas.models.Components)3 JavadocProvider (org.springdoc.core.providers.JavadocProvider)3 Operation (io.swagger.v3.oas.models.Operation)2 ApiResponses (io.swagger.v3.oas.models.responses.ApiResponses)2 Annotation (java.lang.annotation.Annotation)2 Method (java.lang.reflect.Method)2 HashSet (java.util.HashSet)2 MethodParameter (org.springframework.core.MethodParameter)2 JsonView (com.fasterxml.jackson.annotation.JsonView)1 AnnotationsUtils (io.swagger.v3.core.util.AnnotationsUtils)1 Callback (io.swagger.v3.oas.annotations.callbacks.Callback)1 OpenAPI (io.swagger.v3.oas.models.OpenAPI)1 PathItem (io.swagger.v3.oas.models.PathItem)1 HttpMethod (io.swagger.v3.oas.models.PathItem.HttpMethod)1 Paths (io.swagger.v3.oas.models.Paths)1 Content (io.swagger.v3.oas.models.media.Content)1 Schema (io.swagger.v3.oas.models.media.Schema)1 Parameter (io.swagger.v3.oas.models.parameters.Parameter)1 ApiResponse (io.swagger.v3.oas.models.responses.ApiResponse)1 ParameterizedType (java.lang.reflect.ParameterizedType)1