Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

public class CodegenOperation {
public final List<CodegenProperty> responseHeaders = new ArrayList<CodegenProperty>();
public boolean hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams, hasRequiredParams,
public boolean hasAuthMethods, hasConsumes, hasProduces, hasOptionalParams, hasRequiredParams,
returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isVoid = false,
hasVersionHeaders = false, hasVersionQueryParams = false,
Expand Down Expand Up @@ -81,6 +81,15 @@ private static boolean nonEmpty(Map<?, ?> params) {
return params != null && !params.isEmpty();
}

/**
* Check if there's at least one parameter
*
* @return true if parameter exists, false otherwise
*/
public boolean getHasParams() {
return nonEmpty(allParams);
}

/**
* Check if there's at least one body parameter
*
Expand Down Expand Up @@ -362,7 +371,6 @@ public String toString() {
sb.append(", hasAuthMethods=").append(hasAuthMethods);
sb.append(", hasConsumes=").append(hasConsumes);
sb.append(", hasProduces=").append(hasProduces);
sb.append(", hasParams=").append(hasParams);
sb.append(", hasOptionalParams=").append(hasOptionalParams);
sb.append(", hasRequiredParams=").append(hasRequiredParams);
sb.append(", returnTypeIsPrimitive=").append(returnTypeIsPrimitive);
Expand Down Expand Up @@ -445,7 +453,6 @@ public boolean equals(Object o) {
return hasAuthMethods == that.hasAuthMethods &&
hasConsumes == that.hasConsumes &&
hasProduces == that.hasProduces &&
hasParams == that.hasParams &&
hasOptionalParams == that.hasOptionalParams &&
hasRequiredParams == that.hasRequiredParams &&
returnTypeIsPrimitive == that.returnTypeIsPrimitive &&
Expand Down Expand Up @@ -522,7 +529,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {

return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasParams, hasOptionalParams,
return Objects.hash(responseHeaders, hasAuthMethods, hasConsumes, hasProduces, hasOptionalParams,
hasRequiredParams, returnTypeIsPrimitive, returnSimpleType, subresourceOperation, isMap,
isArray, isMultipart, isVoid, isResponseBinary, isResponseFile, isResponseOptional, hasReference,
hasDefaultResponse, hasOnlyDefaultResponse, isRestfulIndex, isRestfulShow, isRestfulCreate, isRestfulUpdate, isRestfulDestroy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4834,9 +4834,6 @@ public CodegenOperation fromOperation(String path,
// legacy support
op.nickname = op.operationId;

if (op.allParams.size() > 0) {
op.hasParams = true;
}
op.hasRequiredParams = op.requiredParams.size() > 0;

// check if the operation has only a single parameter
Expand Down Expand Up @@ -8678,6 +8675,5 @@ protected void handleConstantParams(CodegenOperation operation) {
operation.allParams.add(p);
}
}
operation.hasParams = !operation.allParams.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2386,7 +2386,6 @@ protected void handleImplicitHeaders(CodegenOperation operation) {
operation.allParams.add(p);
}
}
operation.hasParams = !operation.allParams.isEmpty();
}

private boolean shouldBeImplicitHeader(CodegenParameter parameter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,6 @@ public ExtendedCodegenOperation(CodegenOperation o) {
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
this.returnSimpleType = o.returnSimpleType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ public ExtendedCodegenOperation(CodegenOperation o) {
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
this.returnSimpleType = o.returnSimpleType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,6 @@ class ExtendedCodegenOperation extends CodegenOperation {
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
this.returnSimpleType = o.returnSimpleType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,6 @@ public ExtendedCodegenOperation(CodegenOperation o) {
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.hasRequiredParams = o.hasRequiredParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ public ExtendedCodegenOperation(CodegenOperation o) {
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.hasRequiredParams = o.hasRequiredParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} {{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}@RequestPart{{/isArray}}{{^isArray}}{{#reactive}}@RequestPart{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}}
{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} {{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}@RequestPart{{/isArray}}{{^isArray}}{{#reactive}}@RequestPart{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{^required}}{{#useOptional}}Optional<{{/useOptional}}{{/required}}{{{dataType}}}{{^required}}{{#useOptional}}>{{/useOptional}}{{/required}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}}
Original file line number Diff line number Diff line change
Expand Up @@ -5384,6 +5384,37 @@ public void testEnumWithImplements() {
JavaFileAssert.assertThat(files.get("Type.java")).fileContains("Type implements java.io.Serializable {");
}

@Test
public void givenMultipartForm_whenGenerateUsingOptional_thenParameterAreCreatedAsOptional() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/spring/issue_9530.yaml");
final SpringCodegen codegen = new SpringCodegen();
codegen.additionalProperties().put(INTERFACE_ONLY, "true");
codegen.additionalProperties().put(SpringCodegen.USE_OPTIONAL, "true");
codegen.setOpenAPI(openAPI);
codegen.setOutputDir(output.getAbsolutePath());

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);


DefaultGenerator generator = new DefaultGenerator();
generator.setGenerateMetadata(false);
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");

generator.opts(input).generate();

assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/PetApi.java"),
"@Valid @RequestParam(value = \"additionalMetadata\", required = false) Optional<String> additionalMetadata",
"@Valid @RequestParam(value = \"length\", required = true) Integer length");
}

@Test
public void shouldEnableBuiltInValidationOptionWhenSetToTrue() throws IOException {
final SpringCodegen codegen = new SpringCodegen();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
openapi: 3.0.1
info:
version: "1.0.0"
title: use-optional-multipart-spring-boot-request-body-issue
paths:
/pet/{petId}/uploadImage:
post:
tags:
- pet tag
summary: uploads an image
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
requestBody:
content:
multipart/form-data:
schema:
required:
- length
properties:
additionalMetadata:
type: string
description: Additional data to pass to server
length:
type: integer
description: Content length
file:
type: string
description: file to upload
format: binary
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ApiResponse'
security:
- petstore_auth:
- write:pets
- read:pets
components:
schemas:
ApiResponse:
title: An uploaded response
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
description: Describes the result of uploading an image resource
securitySchemes:
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: http://petstore.swagger.io/api/oauth/dialog
scopes:
write:pets: modify pets in your account
read:pets: read your pets
api_key:
type: apiKey
name: api_key
in: header

Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ ResponseEntity<Pet> updatePet(

ResponseEntity<Void> updatePetWithForm(
@PathVariable("petId") Long petId,
@Valid @RequestParam(value = "name", required = false) String name,
@Valid @RequestParam(value = "status", required = false) String status
@Valid @RequestParam(value = "name", required = false) Optional<String> name,
@Valid @RequestParam(value = "status", required = false) Optional<String> status
);


Expand All @@ -189,7 +189,7 @@ ResponseEntity<Void> updatePetWithForm(

ResponseEntity<ModelApiResponse> uploadFile(
@PathVariable("petId") Long petId,
@Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
@Valid @RequestParam(value = "additionalMetadata", required = false) Optional<String> additionalMetadata,
@RequestPart(value = "file", required = false) MultipartFile file
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,16 +396,16 @@ default ResponseEntity<Void> testEndpointParameters(
@ApiParam(value = "None", required = true) @Valid @RequestParam(value = "double", required = true) Double _double,
@ApiParam(value = "None", required = true) @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter,
@ApiParam(value = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte,
@ApiParam(value = "None") @Valid @RequestParam(value = "integer", required = false) Integer integer,
@ApiParam(value = "None") @Valid @RequestParam(value = "int32", required = false) Integer int32,
@ApiParam(value = "None") @Valid @RequestParam(value = "int64", required = false) Long int64,
@ApiParam(value = "None") @Valid @RequestParam(value = "float", required = false) Float _float,
@ApiParam(value = "None") @Valid @RequestParam(value = "string", required = false) String string,
@ApiParam(value = "None") @Valid @RequestParam(value = "integer", required = false) Optional<Integer> integer,
@ApiParam(value = "None") @Valid @RequestParam(value = "int32", required = false) Optional<Integer> int32,
@ApiParam(value = "None") @Valid @RequestParam(value = "int64", required = false) Optional<Long> int64,
@ApiParam(value = "None") @Valid @RequestParam(value = "float", required = false) Optional<Float> _float,
@ApiParam(value = "None") @Valid @RequestParam(value = "string", required = false) Optional<String> string,
@ApiParam(value = "None") @RequestPart(value = "binary", required = false) MultipartFile binary,
@ApiParam(value = "None") @Valid @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
@ApiParam(value = "None") @Valid @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime,
@ApiParam(value = "None") @Valid @RequestParam(value = "password", required = false) String password,
@ApiParam(value = "None") @Valid @RequestParam(value = "callback", required = false) String paramCallback
@ApiParam(value = "None") @Valid @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Optional<LocalDate> date,
@ApiParam(value = "None") @Valid @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Optional<OffsetDateTime> dateTime,
@ApiParam(value = "None") @Valid @RequestParam(value = "password", required = false) Optional<String> password,
@ApiParam(value = "None") @Valid @RequestParam(value = "callback", required = false) Optional<String> paramCallback
) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

Expand Down Expand Up @@ -450,8 +450,8 @@ default ResponseEntity<Void> testEnumParameters(
@ApiParam(value = "Query parameter enum test (string)", allowableValues = "_abc, -efg, (xyz)", defaultValue = "-efg") @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") Optional<String> enumQueryString,
@ApiParam(value = "Query parameter enum test (double)", allowableValues = "1, -2") @Valid @RequestParam(value = "enum_query_integer", required = false) Optional<Integer> enumQueryInteger,
@ApiParam(value = "Query parameter enum test (double)", allowableValues = "1.1, -1.2") @Valid @RequestParam(value = "enum_query_double", required = false) Optional<Double> enumQueryDouble,
@ApiParam(value = "Form parameter enum test (string array)", allowableValues = ">, $", defaultValue = "$") @Valid @RequestPart(value = "enum_form_string_array", required = false) List<String> enumFormStringArray,
@ApiParam(value = "Form parameter enum test (string)", allowableValues = "_abc, -efg, (xyz)", defaultValue = "-efg") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString
@ApiParam(value = "Form parameter enum test (string array)", allowableValues = ">, $", defaultValue = "$") @Valid @RequestPart(value = "enum_form_string_array", required = false) Optional<List<String>> enumFormStringArray,
@ApiParam(value = "Form parameter enum test (string)", allowableValues = "_abc, -efg, (xyz)", defaultValue = "-efg") @Valid @RequestParam(value = "enum_form_string", required = false) Optional<String> enumFormString
) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

Expand Down Expand Up @@ -698,7 +698,7 @@ default ResponseEntity<Integer> testWithResultExample(
default ResponseEntity<ModelApiResponse> uploadFileWithRequiredFile(
@ApiParam(value = "ID of pet to update", required = true) @PathVariable("petId") Long petId,
@ApiParam(value = "file to upload", required = true) @RequestPart(value = "requiredFile", required = true) MultipartFile requiredFile,
@ApiParam(value = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata
@ApiParam(value = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) Optional<String> additionalMetadata
) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ default ResponseEntity<Void> updatePet(

default ResponseEntity<Void> updatePetWithForm(
@ApiParam(value = "ID of pet that needs to be updated", required = true) @PathVariable("petId") Long petId,
@ApiParam(value = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name,
@ApiParam(value = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status
@ApiParam(value = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) Optional<String> name,
@ApiParam(value = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) Optional<String> status
) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

Expand Down Expand Up @@ -388,7 +388,7 @@ default ResponseEntity<Void> updatePetWithForm(

default ResponseEntity<ModelApiResponse> uploadFile(
@ApiParam(value = "ID of pet to update", required = true) @PathVariable("petId") Long petId,
@ApiParam(value = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
@ApiParam(value = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) Optional<String> additionalMetadata,
@ApiParam(value = "file to upload") @RequestPart(value = "file", required = false) MultipartFile file
) {
getRequest().ifPresent(request -> {
Expand Down
Loading