Skip to content

Commit

Permalink
added support for multipart and x-www-form-encoded when callmode is t…
Browse files Browse the repository at this point in the history
…rue (#341)
  • Loading branch information
oscar-ares authored May 7, 2024
1 parent e5dbf2c commit 996f205
Show file tree
Hide file tree
Showing 17 changed files with 1,141 additions and 36 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ As commented above, they both could be used at the same time, setting a double
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.4.1</version>
<version>5.4.2</version>
<executions>
<execution>
<id>asyncapi</id>
Expand Down Expand Up @@ -114,7 +114,7 @@ Apply the plugin in the `build.gradle` file and invoke the task.
```groovy
plugins {
id "java"
id "com.sngular.scs-multiapi-gradle-plugin' version '5.4.1"
id "com.sngular.scs-multiapi-gradle-plugin' version '5.4.2"
openapimodel {
Expand Down Expand Up @@ -153,7 +153,7 @@ which the plugin is designed.
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.4.1</version>
<version>5.4.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
Expand Down Expand Up @@ -584,7 +584,7 @@ file. Here is an example of a basic configuration:
<plugin>
<groupId>com.sngular</groupId>
<artifactId>scs-multiapi-maven-plugin</artifactId>
<version>5.4.1</version>
<version>5.4.2</version>
<executions>
<execution>
<goals>
Expand Down
2 changes: 1 addition & 1 deletion multiapi-engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.sngular</groupId>
<artifactId>multiapi-engine</artifactId>
<version>5.4.1</version>
<version>5.4.2</version>
<packaging>jar</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,22 @@

package com.sngular.api.generator.plugin.openapi.utils;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.function.BiConsumer;

import com.fasterxml.jackson.databind.JsonNode;
import com.sngular.api.generator.plugin.common.tools.ApiTool;
import com.sngular.api.generator.plugin.common.tools.SchemaUtil;
import com.sngular.api.generator.plugin.openapi.exception.DuplicatedOperationException;
import com.sngular.api.generator.plugin.openapi.exception.InvalidOpenAPIException;
import com.sngular.api.generator.plugin.openapi.model.AuthSchemaObject;
import com.sngular.api.generator.plugin.openapi.model.ContentObject;
import com.sngular.api.generator.plugin.openapi.model.GlobalObject;
import com.sngular.api.generator.plugin.openapi.model.*;
import com.sngular.api.generator.plugin.openapi.model.GlobalObject.GlobalObjectBuilder;
import com.sngular.api.generator.plugin.openapi.model.OperationObject;
import com.sngular.api.generator.plugin.openapi.model.ParameterObject;
import com.sngular.api.generator.plugin.openapi.model.PathObject;
import com.sngular.api.generator.plugin.openapi.model.RequestObject;
import com.sngular.api.generator.plugin.openapi.model.ResponseObject;
import com.sngular.api.generator.plugin.openapi.model.SchemaFieldObjectType;
import com.sngular.api.generator.plugin.openapi.model.TypeConstants;
import com.sngular.api.generator.plugin.openapi.parameter.SpecFile;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.lang3.StringUtils;

import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiConsumer;

public class MapperPathUtil {

public static final String INLINE_PARAMETER = "InlineParameter";
Expand Down Expand Up @@ -352,17 +337,22 @@ private static List<ContentObject> mapContentObject(
final Path baseDir) {
final List<ContentObject> contentObjects = new ArrayList<>();
if (Objects.nonNull(content)) {
for (Iterator<String> it = content.fieldNames(); it.hasNext();) {
for (Iterator<String> it = content.fieldNames(); it.hasNext(); ) {
final String mediaType = it.next();
final var schema = ApiTool.getNode(ApiTool.getNode(content, mediaType), SCHEMA);
final String pojoName = preparePojoName(inlineObject, schema, specFile);
final SchemaFieldObjectType dataType = getSchemaType(schema, pojoName, specFile, globalObject, baseDir);
final String importName = getImportFromType(dataType);
SchemaObject schemaObject = null;
if (mediaType.equals("application/x-www-form-urlencoded") || mediaType.equals("multipart/form-data")) {
schemaObject = MapperContentUtil.mapComponentToSchemaObject(globalObject.getSchemaMap(), new HashMap<String, SchemaObject>(), schema, dataType.getBaseType(), specFile, baseDir).get("object");
}
contentObjects.add(ContentObject.builder()
.dataType(dataType)
.name(mediaType)
.importName(importName)
.build());
.dataType(dataType)
.name(mediaType)
.importName(importName)
.schemaObject(schemaObject)
.build());
}
}
return contentObjects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ public class ${className?cap_first}Api {
final HttpHeaders headerParams = new HttpHeaders();
final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
<#if operation.requestObjects?has_content>
<#if operation.requestObjects[0].contentObjects[0].schemaObject?has_content>
<#list operation.requestObjects[0].contentObjects[0].schemaObject.fieldObjectList as field>
formParams.put("${field.baseName}", List.of(${operation.requestObjects[0].contentObjects[0].dataType?api.getVariableNameString()}.get${field.baseName?cap_first}()));
</#list>
</#if>
</#if>

<#if operation.parameterObjects?has_content>
<#list operation.parameterObjects as parameter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,20 @@ public final class OpenApiGeneratorFixtures {
.build()
);

static final List<SpecFile> TEST_REST_CLIENT_API_WITH_REQUEST_OBJECTS_GENERATION = List.of(
SpecFile
.builder()
.filePath("openapigenerator/testRestClientApiWithRequestObjectGeneration/api-test.yml")
.apiPackage("com.sngular.multifileplugin.restclientWithRequestObjects")
.modelPackage("com.sngular.multifileplugin.restclientWithRequestObjects.model")
.clientPackage("com.sngular.multifileplugin.restclientWithRequestObjects.client")
.modelNamePrefix("Api")
.modelNameSuffix("DTO")
.useLombokModelAnnotation(false)
.callMode(true)
.build()
);

static final List<SpecFile> TEST_ENUMS_GENERATION = List.of(
SpecFile
.builder()
Expand Down Expand Up @@ -491,6 +505,7 @@ public final class OpenApiGeneratorFixtures {
.build()
);


static Function<Path, Boolean> validateOneOfInResponse() {

final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/testoneofinresponse";
Expand Down Expand Up @@ -911,6 +926,36 @@ static Function<Path, Boolean> validateRestClientGeneration() {
commonTest(path, expectedTestClientApiFile, expectedTestClientAuthModelFiles, CLIENT_TARGET_API, CLIENT_MODEL_API, Collections.emptyList(), null);
}

static Function<Path, Boolean> validateRestClientWithRequestBodyGeneration() {

final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/restclientWithRequestObjects";

final String CLIENT_TARGET_API = "generated/com/sngular/multifileplugin/restclientWithRequestObjects/client";

final String CLIENT_MODEL_API = "generated/com/sngular/multifileplugin/restclientWithRequestObjects/client/auth";

final String COMMON_PATH = "openapigenerator/testRestClientApiWithRequestObjectGeneration/";

final String ASSETS_PATH = COMMON_PATH + "assets/";

List<String> expectedTestApiFile = List.of(
ASSETS_PATH + "TestApi.java"
);

List<String> expectedTestClientApiFile = List.of(
ASSETS_PATH + "client/ApiRestClient.java"
);

List<String> expectedTestClientAuthModelFiles = List.of(
ASSETS_PATH + "client/auth/Authentication.java",
ASSETS_PATH + "client/auth/HttpBasicAuth.java"
);

return (path) ->
commonTest(path, expectedTestApiFile, Collections.emptyList(), DEFAULT_TARGET_API, null, Collections.emptyList(), null) &&
commonTest(path, expectedTestClientApiFile, expectedTestClientAuthModelFiles, CLIENT_TARGET_API, CLIENT_MODEL_API, Collections.emptyList(), null);
}

static Function<Path, Boolean> validateEnumsGeneration() {

final String DEFAULT_TARGET_API = "generated/com/sngular/multifileplugin/enumgeneration";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ static Stream<Arguments> fileSpecToProcess() {
OpenApiGeneratorFixtures.validateClientPackageWebClientGeneration()),
Arguments.of("testRestClientApiGeneration", OpenApiGeneratorFixtures.TEST_REST_CLIENT_GENERATION,
OpenApiGeneratorFixtures.validateRestClientGeneration()),
Arguments.of("testRestClientApiWithRequestObjectGeneration", OpenApiGeneratorFixtures.TEST_REST_CLIENT_API_WITH_REQUEST_OBJECTS_GENERATION,
OpenApiGeneratorFixtures.validateRestClientWithRequestBodyGeneration()),
Arguments.of("testApiEnumsGeneration", OpenApiGeneratorFixtures.TEST_ENUMS_GENERATION,
OpenApiGeneratorFixtures.validateEnumsGeneration()),
Arguments.of("testApiEnumsLombokGeneration", OpenApiGeneratorFixtures.TEST_ENUMS_LOMBOK_GENERATION,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
openapi: "3.0.0"
info:
version: 1.0.0
title: Sngular Test Api
license:
name: MIT
servers:
- url: http://localhost:8080/v1
paths:
/test/form_url_encoded:
summary: test
get:
summary: Test url form encoded
operationId: test_form_url_encoded
tags:
- test
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
$ref: "#/components/schemas/TestInput"
responses:
'200':
description: Test response
content:
application/json:
schema:
$ref: "#/components/schemas/TestResponse"
/test/multipart:
summary: test
get:
summary: Test multipart
operationId: test_multipart
tags:
- test
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/TestInput"
responses:
'200':
description: Test response
content:
application/json:
schema:
$ref: "#/components/schemas/TestResponse"

components:
schemas:
TestInput:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int32
name:
type: string
TestResponse:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int32
name:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.sngular.multifileplugin.restclient.model;

import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import com.sngular.multifileplugin.restclient.model.exception.ModelClassException;

public class ApiErrorDTO {

@JsonProperty(value ="code")
private final Integer code;
@JsonProperty(value ="message")
private final String message;

private ApiErrorDTO(Integer code, String message) {
this.code = code;
this.message = message;

validateRequiredAttributes();
}

private ApiErrorDTO(ApiErrorDTOBuilder builder) {
this.code = builder.code;
this.message = builder.message;

validateRequiredAttributes();
}

public static ApiErrorDTO.ApiErrorDTOBuilder builder() {
return new ApiErrorDTO.ApiErrorDTOBuilder();
}

public static class ApiErrorDTOBuilder {

private Integer code;
private String message;

public ApiErrorDTO.ApiErrorDTOBuilder code(Integer code) {
this.code = code;
return this;
}

public ApiErrorDTO.ApiErrorDTOBuilder message(String message) {
this.message = message;
return this;
}

public ApiErrorDTO build() {
ApiErrorDTO apiErrorDTO = new ApiErrorDTO(this);
return apiErrorDTO;
}
}


@Schema(name = "code", required = true)
public Integer getCode() {
return code;
}


@Schema(name = "message", required = true)
public String getMessage() {
return message;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ApiErrorDTO apiErrorDTO = (ApiErrorDTO) o;
return Objects.equals(this.code, apiErrorDTO.code) && Objects.equals(this.message, apiErrorDTO.message);
}

@Override
public int hashCode() {
return Objects.hash(code, message);
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ApiErrorDTO{");
sb.append(" code:").append(code).append(",");
sb.append(" message:").append(message);
sb.append("}");
return sb.toString();
}




private void validateRequiredAttributes() {
boolean satisfiedCondition = true;

if (!Objects.nonNull(this.code)) {
satisfiedCondition = false;
} else if (!Objects.nonNull(this.message)) {
satisfiedCondition = false;
}

if (!satisfiedCondition) {
throw new ModelClassException("ApiErrorDTO");
}
}

}
Loading

0 comments on commit 996f205

Please sign in to comment.