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

org.springdoc.core.AbstractRequestBuilder Maven / Gradle / Ivy

package org.springdoc.core;

import static org.springdoc.core.Constants.*;

import java.lang.annotation.Annotation;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.method.HandlerMethod;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;

public abstract class AbstractRequestBuilder {

	private ParameterBuilder parameterBuilder;

	private RequestBodyBuilder requestBodyBuilder;

	protected AbstractRequestBuilder(ParameterBuilder parameterBuilder, RequestBodyBuilder requestBodyBuilder) {
		super();
		this.parameterBuilder = parameterBuilder;
		this.requestBodyBuilder = requestBodyBuilder;
	}

	protected abstract boolean isParamTypeToIgnore(Class paramType);

	public Operation build(Components components, HandlerMethod handlerMethod, RequestMethod requestMethod,
			Operation operation, MediaAttributes mediaAttributes) {
		// Documentation
		operation.setOperationId(handlerMethod.getMethod().getName());
		// requests
		LocalVariableTableParameterNameDiscoverer d = new LocalVariableTableParameterNameDiscoverer();
		String[] pNames = d.getParameterNames(handlerMethod.getMethod());
		List operationParameters = new ArrayList<>();
		java.lang.reflect.Parameter[] parameters = handlerMethod.getMethod().getParameters();

		for (int i = 0; i < pNames.length; i++) {
			// check if query param
			Parameter parameter = null;
			Class paramType = parameters[i].getType();
			io.swagger.v3.oas.annotations.Parameter parameterDoc = parameterBuilder.getParameterAnnotation(
					handlerMethod, parameters[i], i, io.swagger.v3.oas.annotations.Parameter.class);

			// use documentation as reference
			if (parameterDoc != null) {
				if (parameterDoc.hidden()) {
					continue;
				}
				parameter = parameterBuilder.buildParameterFromDoc(parameterDoc, null);
			}

			if (!isParamTypeToIgnore(paramType)) {
				parameter = buildParams(pNames[i], components, parameters[i], i, parameter, handlerMethod,
						requestMethod);
				if (parameter != null && (parameter.getName() != null || parameter.get$ref() != null)) {
					applyBeanValidatorAnnotations(parameter, Arrays.asList(parameters[i].getAnnotations()));
					operationParameters.add(parameter);
				} else if (!RequestMethod.GET.equals(requestMethod)) {
					RequestBody requestBody = requestBodyBuilder.calculateRequestBody(components, handlerMethod,
							mediaAttributes, pNames, parameters, i, parameterDoc);
					operation.setRequestBody(requestBody);
				}
			}
		}
		if (!CollectionUtils.isEmpty(operationParameters)) {
			operation.setParameters(operationParameters);
		}

		return operation;
	}

	private Parameter buildParams(String pName, Components components, java.lang.reflect.Parameter parameters,
			int index, Parameter parameter, HandlerMethod handlerMethod, RequestMethod requestMethod) {
		RequestHeader requestHeader = parameterBuilder.getParameterAnnotation(handlerMethod, parameters, index,
				RequestHeader.class);
		RequestParam requestParam = parameterBuilder.getParameterAnnotation(handlerMethod, parameters, index,
				RequestParam.class);
		PathVariable pathVar = parameterBuilder.getParameterAnnotation(handlerMethod, parameters, index,
				PathVariable.class);

		if (requestHeader != null) {
			String name = StringUtils.isBlank(requestHeader.value()) ? pName : requestHeader.value();
			parameter = this.buildParam(HEADER_PARAM, components, parameters, requestHeader.required(), name,
					parameter);
		} else if (requestParam != null) {
			String name = StringUtils.isBlank(requestParam.value()) ? pName : requestParam.value();
			parameter = this.buildParam(QUERY_PARAM, components, parameters, requestParam.required(), name, parameter);
		} else if (pathVar != null) {
			String name = StringUtils.isBlank(pathVar.value()) ? pName : pathVar.value();
			// check if PATH PARAM
			parameter = this.buildParam(PATH_PARAM, components, parameters, Boolean.TRUE, name, parameter);
		}
		// By default
		if (RequestMethod.GET.equals(requestMethod)) {
			if (parameter == null) {
				parameter = this.buildParam(QUERY_PARAM, components, parameters, Boolean.TRUE, pName, null);
			} else if (parameter.getName() == null) {
				parameter.setName(pName);
			}
		}
		return parameter;
	}

	private Parameter buildParam(String in, Components components, java.lang.reflect.Parameter parameters,
			Boolean required, String name, Parameter parameter) {
		if (parameter == null)
			parameter = new Parameter();
		parameter.setIn(in);
		parameter.setRequired(required);
		parameter.setName(name);
		if (parameter.getSchema() == null) {
			Schema schema = parameterBuilder.calculateSchema(components, parameters, name, null);
			parameter.setSchema(schema);
		}
		return parameter;
	}

	/**
	 * This is mostly a duplicate of
	 * {@link io.swagger.v3.core.jackson.ModelResolver#applyBeanValidatorAnnotations}.
	 *
	 * @param parameter
	 * @param annotations
	 */
	private void applyBeanValidatorAnnotations(final Parameter parameter, final List annotations) {
		Map annos = new HashMap<>();
		if (annotations != null) {
			annotations.forEach(annotation -> annos.put(annotation.annotationType().getName(), annotation));
		}

		if (annos.containsKey(NotNull.class.getName())) {
			parameter.setRequired(true);
		}

		Schema schema = parameter.getSchema();

		if (annos.containsKey(Min.class.getName())) {
			Min min = (Min) annos.get(Min.class.getName());
			schema.setMinimum(BigDecimal.valueOf(min.value()));
		}
		if (annos.containsKey(Max.class.getName())) {
			Max max = (Max) annos.get(Max.class.getName());
			schema.setMaximum(BigDecimal.valueOf(max.value()));
		}
		calculateSize(annos, schema);
		if (annos.containsKey(DecimalMin.class.getName())) {
			DecimalMin min = (DecimalMin) annos.get(DecimalMin.class.getName());
			if (min.inclusive()) {
				schema.setMinimum(BigDecimal.valueOf(Double.valueOf(min.value())));
			} else {
				schema.setExclusiveMinimum(!min.inclusive());
			}
		}
		if (annos.containsKey(DecimalMax.class.getName())) {
			DecimalMax max = (DecimalMax) annos.get(DecimalMax.class.getName());
			if (max.inclusive()) {
				schema.setMaximum(BigDecimal.valueOf(Double.valueOf(max.value())));
			} else {
				schema.setExclusiveMaximum(!max.inclusive());
			}
		}
		if (annos.containsKey(Pattern.class.getName())) {
			Pattern pattern = (Pattern) annos.get(Pattern.class.getName());
			schema.setPattern(pattern.regexp());
		}
	}

	private void calculateSize(Map annos, Schema schema) {
		if (annos.containsKey(Size.class.getName())) {
			Size size = (Size) annos.get(Size.class.getName());
			if (OPENAPI_ARRAY_TYPE.equals(schema.getType())) {
				schema.setMinItems(size.min());
				schema.setMaxItems(size.max());
			} else if (OPENAPI_STRING_TYPE.equals(schema.getType())) {
				schema.setMinLength(size.min());
				schema.setMaxLength(size.max());
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy