|
26 | 26 |
|
27 | 27 | package org.springdoc.core.service; |
28 | 28 |
|
| 29 | +import java.io.InputStream; |
| 30 | +import java.io.OutputStream; |
| 31 | +import java.io.Reader; |
| 32 | +import java.io.Writer; |
29 | 33 | import java.lang.annotation.Annotation; |
30 | 34 | import java.lang.reflect.Method; |
31 | 35 | import java.math.BigDecimal; |
| 36 | +import java.security.Principal; |
| 37 | +import java.time.ZoneId; |
32 | 38 | import java.util.ArrayList; |
33 | 39 | import java.util.Arrays; |
34 | 40 | import java.util.Collection; |
|
37 | 43 | import java.util.Iterator; |
38 | 44 | import java.util.LinkedHashMap; |
39 | 45 | import java.util.List; |
| 46 | +import java.util.Locale; |
40 | 47 | import java.util.Map; |
41 | 48 | import java.util.Map.Entry; |
42 | 49 | import java.util.Objects; |
43 | 50 | import java.util.Optional; |
44 | 51 | import java.util.Set; |
| 52 | +import java.util.TimeZone; |
45 | 53 | import java.util.stream.Collectors; |
46 | 54 | import java.util.stream.Stream; |
47 | 55 |
|
48 | 56 | import com.fasterxml.jackson.annotation.JsonView; |
49 | 57 | import io.swagger.v3.core.util.PrimitiveType; |
| 58 | +import io.swagger.v3.oas.annotations.Parameters; |
50 | 59 | import io.swagger.v3.oas.annotations.enums.ParameterIn; |
51 | 60 | import io.swagger.v3.oas.models.Components; |
52 | 61 | import io.swagger.v3.oas.models.OpenAPI; |
53 | 62 | import io.swagger.v3.oas.models.Operation; |
54 | | -import io.swagger.v3.oas.models.media.Content; |
55 | | -import io.swagger.v3.oas.models.media.MediaType; |
56 | 63 | import io.swagger.v3.oas.models.media.Schema; |
57 | 64 | import io.swagger.v3.oas.models.media.StringSchema; |
58 | 65 | import io.swagger.v3.oas.models.parameters.Parameter; |
|
78 | 85 | import org.springframework.core.MethodParameter; |
79 | 86 | import org.springframework.core.annotation.AnnotatedElementUtils; |
80 | 87 | import org.springframework.http.HttpMethod; |
| 88 | +import org.springframework.ui.Model; |
| 89 | +import org.springframework.ui.ModelMap; |
81 | 90 | import org.springframework.util.CollectionUtils; |
82 | 91 | import org.springframework.validation.BindingResult; |
83 | 92 | import org.springframework.validation.Errors; |
84 | 93 | import org.springframework.web.bind.annotation.PathVariable; |
85 | 94 | import org.springframework.web.bind.annotation.RequestAttribute; |
86 | 95 | import org.springframework.web.bind.annotation.RequestMethod; |
87 | 96 | import org.springframework.web.bind.annotation.RequestParam; |
| 97 | +import org.springframework.web.bind.annotation.RequestPart; |
88 | 98 | import org.springframework.web.bind.annotation.ValueConstants; |
89 | 99 | import org.springframework.web.bind.support.SessionStatus; |
90 | 100 | import org.springframework.web.context.request.NativeWebRequest; |
|
97 | 107 | import static org.springdoc.core.utils.Constants.OPENAPI_ARRAY_TYPE; |
98 | 108 | import static org.springdoc.core.utils.Constants.OPENAPI_STRING_TYPE; |
99 | 109 | import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations; |
| 110 | +import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; |
100 | 111 | import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; |
101 | 112 |
|
102 | 113 | /** |
@@ -130,18 +141,18 @@ public abstract class AbstractRequestService { |
130 | 141 | static { |
131 | 142 | PARAM_TYPES_TO_IGNORE.add(WebRequest.class); |
132 | 143 | PARAM_TYPES_TO_IGNORE.add(NativeWebRequest.class); |
133 | | - PARAM_TYPES_TO_IGNORE.add(java.security.Principal.class); |
| 144 | + PARAM_TYPES_TO_IGNORE.add(Principal.class); |
134 | 145 | PARAM_TYPES_TO_IGNORE.add(HttpMethod.class); |
135 | | - PARAM_TYPES_TO_IGNORE.add(java.util.Locale.class); |
136 | | - PARAM_TYPES_TO_IGNORE.add(java.util.TimeZone.class); |
137 | | - PARAM_TYPES_TO_IGNORE.add(java.io.InputStream.class); |
138 | | - PARAM_TYPES_TO_IGNORE.add(java.time.ZoneId.class); |
139 | | - PARAM_TYPES_TO_IGNORE.add(java.io.Reader.class); |
140 | | - PARAM_TYPES_TO_IGNORE.add(java.io.OutputStream.class); |
141 | | - PARAM_TYPES_TO_IGNORE.add(java.io.Writer.class); |
142 | | - PARAM_TYPES_TO_IGNORE.add(java.util.Map.class); |
143 | | - PARAM_TYPES_TO_IGNORE.add(org.springframework.ui.Model.class); |
144 | | - PARAM_TYPES_TO_IGNORE.add(org.springframework.ui.ModelMap.class); |
| 146 | + PARAM_TYPES_TO_IGNORE.add(Locale.class); |
| 147 | + PARAM_TYPES_TO_IGNORE.add(TimeZone.class); |
| 148 | + PARAM_TYPES_TO_IGNORE.add(InputStream.class); |
| 149 | + PARAM_TYPES_TO_IGNORE.add(ZoneId.class); |
| 150 | + PARAM_TYPES_TO_IGNORE.add(Reader.class); |
| 151 | + PARAM_TYPES_TO_IGNORE.add(OutputStream.class); |
| 152 | + PARAM_TYPES_TO_IGNORE.add(Writer.class); |
| 153 | + PARAM_TYPES_TO_IGNORE.add(Map.class); |
| 154 | + PARAM_TYPES_TO_IGNORE.add(Model.class); |
| 155 | + PARAM_TYPES_TO_IGNORE.add(ModelMap.class); |
145 | 156 | PARAM_TYPES_TO_IGNORE.add(Errors.class); |
146 | 157 | PARAM_TYPES_TO_IGNORE.add(BindingResult.class); |
147 | 158 | PARAM_TYPES_TO_IGNORE.add(SessionStatus.class); |
@@ -240,7 +251,7 @@ public static boolean isRequestTypeToIgnore(Class<?> rawClass) { |
240 | 251 | */ |
241 | 252 | @SuppressWarnings("unchecked") |
242 | 253 | public static Collection<Parameter> getHeaders(MethodAttributes methodAttributes, Map<ParameterId, Parameter> map) { |
243 | | - for (Map.Entry<String, String> entry : methodAttributes.getHeaders().entrySet()) { |
| 254 | + for (Entry<String, String> entry : methodAttributes.getHeaders().entrySet()) { |
244 | 255 | StringSchema schema = new StringSchema(); |
245 | 256 | if (StringUtils.isNotEmpty(entry.getValue())) |
246 | 257 | schema.addEnumItem(entry.getValue()); |
@@ -291,7 +302,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod, |
291 | 302 |
|
292 | 303 | for (MethodParameter methodParameter : parameters) { |
293 | 304 | // check if query param |
294 | | - Parameter parameter; |
| 305 | + Parameter parameter = null; |
295 | 306 | io.swagger.v3.oas.annotations.Parameter parameterDoc = AnnotatedElementUtils.findMergedAnnotation( |
296 | 307 | AnnotatedElementUtils.forAnnotations(methodParameter.getParameterAnnotations()), |
297 | 308 | io.swagger.v3.oas.annotations.Parameter.class); |
@@ -321,12 +332,10 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod, |
321 | 332 |
|
322 | 333 | if (!isParamToIgnore(methodParameter)) { |
323 | 334 | parameter = buildParams(parameterInfo, components, requestMethod, methodAttributes, openAPI.getOpenapi()); |
324 | | - // Merge with the operation parameters |
325 | | - parameter = GenericParameterService.mergeParameter(operationParameters, parameter); |
326 | | - |
327 | 335 | List<Annotation> parameterAnnotations = List.of(getParameterAnnotations(methodParameter)); |
328 | | - |
329 | | - if (isValidParameter(parameter)) { |
| 336 | + if (isValidParameter(parameter,methodAttributes)) { |
| 337 | + // Merge with the operation parameters |
| 338 | + parameter = GenericParameterService.mergeParameter(operationParameters, parameter); |
330 | 339 | // Add param javadoc |
331 | 340 | if (StringUtils.isBlank(parameter.getDescription()) && javadocProvider != null) { |
332 | 341 | String paramJavadocDescription = parameterBuilder.getParamJavadoc(javadocProvider, methodParameter); |
@@ -359,7 +368,7 @@ else if (!RequestMethod.GET.equals(requestMethod) || OpenApiVersion.OPENAPI_3_1. |
359 | 368 | Parameter parameter = entry.getValue(); |
360 | 369 | if (!ParameterIn.PATH.toString().equals(parameter.getIn()) && !ParameterIn.HEADER.toString().equals(parameter.getIn()) |
361 | 370 | && !ParameterIn.COOKIE.toString().equals(parameter.getIn())) { |
362 | | - io.swagger.v3.oas.models.media.Schema<?> itemSchema = new io.swagger.v3.oas.models.media.Schema<>(); |
| 371 | + Schema<?> itemSchema = new Schema<>(); |
363 | 372 | itemSchema.setName(entry.getKey().getpName()); |
364 | 373 | itemSchema.setDescription(parameter.getDescription()); |
365 | 374 | itemSchema.setDeprecated(parameter.getDeprecated()); |
@@ -388,7 +397,7 @@ private LinkedHashMap<ParameterId, Parameter> getParameterLinkedHashMap(Componen |
388 | 397 | throw new IllegalStateException(String.format("Duplicate key %s", u)); |
389 | 398 | }, LinkedHashMap::new)); |
390 | 399 |
|
391 | | - for (Map.Entry<ParameterId, io.swagger.v3.oas.annotations.Parameter> entry : parametersDocMap.entrySet()) { |
| 400 | + for (Entry<ParameterId, io.swagger.v3.oas.annotations.Parameter> entry : parametersDocMap.entrySet()) { |
392 | 401 | ParameterId parameterId = entry.getKey(); |
393 | 402 | if (parameterId != null && !map.containsKey(parameterId) && !entry.getValue().hidden()) { |
394 | 403 | Parameter parameter = parameterBuilder.buildParameterFromDoc(entry.getValue(), components, methodAttributes.getJsonViewAnnotation(), methodAttributes.getLocale()); |
@@ -512,11 +521,12 @@ private void setParams(Operation operation, List<Parameter> operationParameters, |
512 | 521 | /** |
513 | 522 | * Is valid parameter boolean. |
514 | 523 | * |
515 | | - * @param parameter the parameter |
| 524 | + * @param parameter the parameter |
| 525 | + * @param methodAttributes the method attributes |
516 | 526 | * @return the boolean |
517 | 527 | */ |
518 | | - public boolean isValidParameter(Parameter parameter) { |
519 | | - return parameter != null && (parameter.getName() != null || parameter.get$ref() != null); |
| 528 | + public boolean isValidParameter(Parameter parameter, MethodAttributes methodAttributes ) { |
| 529 | + return parameter != null && (parameter.getName() != null || parameter.get$ref() != null) && !(Arrays.asList(methodAttributes.getMethodConsumes()).contains(APPLICATION_FORM_URLENCODED_VALUE) && ParameterIn.QUERY.toString().equals(parameter.getIn())); |
520 | 530 | } |
521 | 531 |
|
522 | 532 | /** |
@@ -640,11 +650,6 @@ public void applyBeanValidatorAnnotations(final RequestBody requestBody, final L |
640 | 650 |
|
641 | 651 | if (validationExists || (!isOptional && (springRequestBodyRequired || swaggerRequestBodyRequired))) |
642 | 652 | requestBody.setRequired(true); |
643 | | - Content content = requestBody.getContent(); |
644 | | - for (MediaType mediaType : content.values()) { |
645 | | - Schema<?> schema = mediaType.getSchema(); |
646 | | - applyValidationsToSchema(annos, schema); |
647 | | - } |
648 | 653 | } |
649 | 654 |
|
650 | 655 | /** |
@@ -703,10 +708,10 @@ else if (OPENAPI_STRING_TYPE.equals(schema.getType())) { |
703 | 708 | private Map<ParameterId, io.swagger.v3.oas.annotations.Parameter> getApiParameters(Method method) { |
704 | 709 | Class<?> declaringClass = method.getDeclaringClass(); |
705 | 710 |
|
706 | | - Set<io.swagger.v3.oas.annotations.Parameters> apiParametersDoc = AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.Parameters.class); |
| 711 | + Set<Parameters> apiParametersDoc = AnnotatedElementUtils.findAllMergedAnnotations(method, Parameters.class); |
707 | 712 | LinkedHashMap<ParameterId, io.swagger.v3.oas.annotations.Parameter> apiParametersMap = apiParametersDoc.stream().flatMap(x -> Stream.of(x.value())).collect(Collectors.toMap(ParameterId::new, x -> x, (e1, e2) -> e2, LinkedHashMap::new)); |
708 | 713 |
|
709 | | - Set<io.swagger.v3.oas.annotations.Parameters> apiParametersDocDeclaringClass = AnnotatedElementUtils.findAllMergedAnnotations(declaringClass, io.swagger.v3.oas.annotations.Parameters.class); |
| 714 | + Set<Parameters> apiParametersDocDeclaringClass = AnnotatedElementUtils.findAllMergedAnnotations(declaringClass, Parameters.class); |
710 | 715 | LinkedHashMap<ParameterId, io.swagger.v3.oas.annotations.Parameter> apiParametersDocDeclaringClassMap = apiParametersDocDeclaringClass.stream().flatMap(x -> Stream.of(x.value())).collect(Collectors.toMap(ParameterId::new, x -> x, (e1, e2) -> e2, LinkedHashMap::new)); |
711 | 716 | apiParametersMap.putAll(apiParametersDocDeclaringClassMap); |
712 | 717 |
|
@@ -803,9 +808,9 @@ private boolean checkRequestBodyAnnotation(MethodParameter methodParameter) { |
803 | 808 | * @return the boolean |
804 | 809 | */ |
805 | 810 | private boolean checkFile(MethodParameter methodParameter) { |
806 | | - if (methodParameter.getParameterAnnotation(org.springframework.web.bind.annotation.RequestPart.class) != null) |
| 811 | + if (methodParameter.getParameterAnnotation(RequestPart.class) != null) |
807 | 812 | return true; |
808 | | - else if (methodParameter.getParameterAnnotation(org.springframework.web.bind.annotation.RequestParam.class) != null) { |
| 813 | + else if (methodParameter.getParameterAnnotation(RequestParam.class) != null) { |
809 | 814 | return isFile(methodParameter.getParameterType()); |
810 | 815 | } |
811 | 816 | return false; |
|
0 commit comments