Skip to content

Commit

Permalink
265 supplier producer code is generated exclusively (#267)
Browse files Browse the repository at this point in the history
* #262 Fix to String generation.

* #262 Fix to String generation.

* #265 Fix Wrong folder generation

* #251 Fix Parameter without description

* #251 Fix Parameter without description

* #251 Fix Parameter without description

* #251 Fix Parameter without description

* #251 Fix Parameter without description
  • Loading branch information
jemacineiras authored Aug 8, 2023
1 parent d70f7cd commit 370ac0c
Show file tree
Hide file tree
Showing 60 changed files with 949 additions and 956 deletions.
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>4.9.6</version>
<version>4.9.7</version>
<packaging>jar</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.sngular.api.generator.plugin.openapi.utils.MapperUtil;
import com.sngular.api.generator.plugin.openapi.utils.OpenApiUtil;
import freemarker.template.TemplateException;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;

Expand Down Expand Up @@ -164,13 +165,13 @@ private void createAuthTemplates(final SpecFile specFile) throws TemplateExcepti
}

private GlobalObject createApiTemplate(final SpecFile specFile, final String filePathToSave, final JsonNode openAPI) {
final Map<String, Map<String, JsonNode>> apis = OpenApiUtil.mapApiGroups(openAPI, specFile.isUseTagsGroup());
final MultiValuedMap<String, Map<String, JsonNode>> apis = OpenApiUtil.mapApiGroups(openAPI, specFile.isUseTagsGroup());
final var authSchemaList = MapperAuthUtil.createAuthSchemaList(openAPI);
final GlobalObject globalObject = MapperPathUtil.mapOpenApiObjectToOurModels(openAPI, authSchemaList);

for (Map.Entry<String, Map<String, JsonNode>> apisEntry : apis.entrySet()) {
final String javaFileName = OpenApiUtil.processJavaFileName(apisEntry.getKey());
final List<PathObject> pathObjects = MapperPathUtil.mapPathObjects(specFile, apisEntry, globalObject, baseDir);
for (var apisKey : apis.keySet()) {
final String javaFileName = OpenApiUtil.processJavaFileName(apisKey);
final List<PathObject> pathObjects = MapperPathUtil.mapPathObjects(specFile, apis.get(apisKey), globalObject, baseDir);
final AuthObject authObject = MapperAuthUtil.getApiAuthObject(globalObject.getAuthSchemas(), pathObjects);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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;
Expand Down Expand Up @@ -71,15 +72,17 @@ private static List<String> getSecurityRequirementList(final JsonNode securityNo
return authSecList;
}

public static List<PathObject> mapPathObjects(final SpecFile specFile, final Entry<String, Map<String, JsonNode>> path, final GlobalObject globalObject, final Path baseDir) {
public static List<PathObject> mapPathObjects(final SpecFile specFile, final Collection<Map<String, JsonNode>> path, final GlobalObject globalObject, final Path baseDir) {
final List<PathObject> pathObjects = new ArrayList<>();
for (Entry<String, JsonNode> pathItem : path.getValue().entrySet()) {
final PathObject pathObject = PathObject.builder()
.pathName(pathItem.getKey())
.globalObject(globalObject)
.operationObjects(mapOperationObject(specFile, pathItem, globalObject, baseDir))
.build();
pathObjects.add(pathObject);
for (var pathMap : path) {
for (var pathItem : pathMap.entrySet()) {
final PathObject pathObject = PathObject.builder()
.pathName(pathItem.getKey())
.globalObject(globalObject)
.operationObjects(mapOperationObject(specFile, pathItem, globalObject, baseDir))
.build();
pathObjects.add(pathObject);
}
}

return pathObjects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@

public class OpenApiUtil {

static final ObjectMapper PARSER = new ObjectMapper(new YAMLFactory());
public static final String PATHS = "paths";

static final ObjectMapper PARSER = new ObjectMapper(new YAMLFactory());
static final Set<String> REST_VERB_SET = Set.of("get", "post", "delete", "patch", "put");
public static final String PATHS = "paths";

private OpenApiUtil() {}

public static Map<String, Map<String, JsonNode>> mapApiGroups(final JsonNode openAPI, final boolean groupByTags) {
final Map<String, Map<String, JsonNode>> mapApis = new HashMap<>();
public static MultiValuedMap<String, Map<String, JsonNode>> mapApiGroups(final JsonNode openAPI, final boolean groupByTags) {
final MultiValuedMap<String, Map<String, JsonNode>> mapApis = new ArrayListValuedHashMap<>();
final var pathList = openAPI.findValue(PATHS).fields();
if (pathList.hasNext()) {
mapApis.putAll(groupByTags ? mapApiGroupsByTags(pathList) : mapApiGroupsByUrl(openAPI));
Expand All @@ -54,52 +54,38 @@ public static Map<String, Map<String, JsonNode>> mapApiGroups(final JsonNode ope
return mapApis;
}

private static Map<String, Map<String, JsonNode>> mapApiGroupsByTags(final Iterator<Entry<String, JsonNode>> pathList) {
private static MultiValuedMap<String, Map<String, JsonNode>> mapApiGroupsByTags(final Iterator<Entry<String, JsonNode>> pathList) {

final Map<String, Map<String, JsonNode>> mapApis = new HashMap<>();
final MultiValuedMap<String, Map<String, JsonNode>> mapApis = new ArrayListValuedHashMap<>();
while (pathList.hasNext()) {
final Entry<String, JsonNode> openAPIPath = pathList.next();
final var mapMethodsByTag = getMapMethodsByTag(openAPIPath);
for (Entry<String, Map<String, JsonNode>> tagMethodEntry : mapMethodsByTag.entries()) {
mapApis.compute(tagMethodEntry.getKey(), (key, value) -> initOrInsert(tagMethodEntry.getValue(), value));
}
mapApis.putAll(getMapMethodsByTag(openAPIPath));
}

return mapApis;

}

private static Map<String, JsonNode> initOrInsert(final Map<String, JsonNode> mapPathMethod, final Map<String, JsonNode> value) {
var newValue = value;
if (Objects.isNull(newValue)) {
newValue = new HashMap<>();
}
newValue.putAll(mapPathMethod);

return newValue;
}

private static MultiValuedMap<String, Map<String, JsonNode>> getMapMethodsByTag(final Entry<String, JsonNode> pathItem) {
final MultiValuedMap<String, Map<String, JsonNode>> mapByTag = new ArrayListValuedHashMap<>();
final var operations = IteratorUtils.filteredIterator(pathItem.getValue().fields(), opProperty -> REST_VERB_SET.contains(opProperty.getKey()));
while (operations.hasNext()) {
final var method = operations.next();
if (ApiTool.hasNode(method.getValue(), "tags")) {
final var tag = ApiTool.getNode(method.getValue(), "tags").elements().next();
mapByTag.put(tag.asText(), Map.of(pathItem.getKey(), new ObjectNode(JsonNodeFactory.instance, Map.ofEntries(method))));
final var tag = ApiTool.getNode(method.getValue(), "tags").elements().next().asText();
mapByTag.put(tag, Map.of(pathItem.getKey(), new ObjectNode(JsonNodeFactory.instance, Map.ofEntries(method))));
}
}
return mapByTag;
}

private static Map<String, Map<String, JsonNode>> mapApiGroupsByUrl(final JsonNode openAPI) {
final var mapByUrl = new HashMap<String, Map<String, JsonNode>>();
private static MultiValuedMap<String, Map<String, JsonNode>> mapApiGroupsByUrl(final JsonNode openAPI) {
final var mapByUrl = new ArrayListValuedHashMap<String, Map<String, JsonNode>>();

for (Iterator<String> it = openAPI.get(PATHS).fieldNames(); it.hasNext();) {
final var pathUrl = it.next();
final String[] pathName = pathUrl.split("/");
mapByUrl.putIfAbsent(pathName[1], new HashMap<>());
mapByUrl.get(pathName[1]).put(pathUrl, openAPI.get(PATHS).get(pathUrl));
mapByUrl.put(pathName[1], Map.of(pathUrl, openAPI.get(PATHS).get(pathUrl)));
}

return mapByUrl;
Expand Down
20 changes: 10 additions & 10 deletions multiapi-engine/src/main/resources/templates/openapi/template.ftlh
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ public interface ${className?cap_first}Api {
/**
* ${operation.operationType} ${path.pathName}<#if operation.summary?has_content>: ${operation.summary}</#if><#if operation.responseObjects?has_content>
<#if operation.parameterObjects?has_content>
*<#list operation.parameterObjects as parameter> @param ${parameter.name} ${parameter.description} ${parameter.required?c}</#list>
*<#list operation.parameterObjects as parameter> @param ${parameter.name} <#if parameter.description?has_content>${parameter.description} </#if>${parameter.required?c}</#list>
</#if>
<#if path.parameterObjects?has_content>
*<#list path.parameterObjects as parameter> @param ${parameter.name} ${parameter.description} ${parameter.required?c}</#list>
*<#list path.parameterObjects as parameter> @param ${parameter.name} <#if parameter.description?has_content>${parameter.description} </#if>${parameter.required?c}</#list>
</#if>
<#if operation.requestObjects?has_content>
*<#list operation.requestObjects as request><#list request.contentObjects as content> @param ${content.dataType?api.getVariableNameString()}<#if content?has_next>, </#if></#list>${request.description! ""}<#if request.required == true> (required)</#if></#list>
Expand All @@ -70,13 +70,13 @@ public interface ${className?cap_first}Api {
*/

@Operation(
operationId = "${operation.operationId}",<#if operation.summary?has_content>
summary = "${operation.summary}",</#if>
tags = {<#list operation.tags as tag>"${tag}"</#list>}<#if operation.responseObjects?has_content>,
responses = {
<#list operation.responseObjects as response> @ApiResponse(responseCode = "${response.responseName}", description = "${response.description}"<#if response.contentObjects?has_content>, content = @Content(<#list response.contentObjects as content>mediaType = "${content.name}", schema = @Schema(implementation = ${content.dataType?api.getClassString()}))</#list></#if>)<#if !response?is_last>,</#if>
operationId = "${operation.operationId}",<#if operation.summary?has_content>
summary = "${operation.summary}",</#if>
tags = {<#list operation.tags as tag>"${tag}"</#list>}<#if operation.responseObjects?has_content>,
responses = {
<#list operation.responseObjects as response> @ApiResponse(responseCode = "${response.responseName}", description = "${response.description}"<#if response.contentObjects?has_content>, content = @Content(<#list response.contentObjects as content>mediaType = "${content.name}", schema = @Schema(implementation = ${content.dataType?api.getClassString()}))</#list></#if>)<#if !response?is_last>,</#if>
</#list>
}</#if>
}</#if>
)
@RequestMapping(
method = RequestMethod.${operation.operationType},
Expand All @@ -86,8 +86,8 @@ public interface ${className?cap_first}Api {

default ResponseEntity<@compress single_line=true><#if operation.responseObjects[0].contentObjects[0]??>
<${operation.responseObjects[0].contentObjects[0].dataType}<#else><Void</#if>></@compress> ${operation.operationId}(<@compress single_line=true>
<#if operation.parameterObjects?has_content><#list operation.parameterObjects as parameter> @Parameter(name = "${parameter.name}", description = "${parameter.description}", required = ${parameter.required?c}, schema = @Schema(description = "")) <#if parameter.in == "path"> @PathVariable("${parameter.name}") <#elseif parameter.in == "query"> @RequestParam(required = ${parameter.required?c}) </#if> ${parameter.dataType} ${parameter.name} <#if parameter?has_next || operation.requestObjects?has_content>, </#if></#list></#if>
<#if path.parameterObjects?has_content><#list path.parameterObjects as parameter> @Parameter(name = "${parameter.name}", description = "${parameter.description}", required = ${parameter.required?c}, schema = @Schema(description = "")) <#if parameter.in == "path"> @PathVariable("${parameter.name}") <#elseif parameter.in == "query"> @RequestParam(required = ${parameter.required?c}) </#if> ${parameter.dataType} ${parameter.name} <#if parameter?has_next || operation.requestObjects?has_content>, </#if></#list></#if>
<#if operation.parameterObjects?has_content><#list operation.parameterObjects as parameter> @Parameter(name = "${parameter.name}", <#if parameter.description?has_content>description = "${parameter.description}", </#if>required = ${parameter.required?c}, schema = @Schema(description = "")) <#if parameter.in == "path"> @PathVariable("${parameter.name}") <#elseif parameter.in == "query"> @RequestParam(required = ${parameter.required?c}) </#if> ${parameter.dataType} ${parameter.name} <#if parameter?has_next || operation.requestObjects?has_content>, </#if></#list></#if>
<#if path.parameterObjects?has_content><#list path.parameterObjects as parameter> @Parameter(name = "${parameter.name}", <#if parameter.description?has_content>description = "${parameter.description}", </#if>required = ${parameter.required?c}, schema = @Schema(description = "")) <#if parameter.in == "path"> @PathVariable("${parameter.name}") <#elseif parameter.in == "query"> @RequestParam(required = ${parameter.required?c}) </#if> ${parameter.dataType} ${parameter.name} <#if parameter?has_next || operation.requestObjects?has_content>, </#if></#list></#if>
<#if operation.requestObjects?has_content><#list operation.requestObjects as request> @Parameter(name = "${request.contentObjects[0].dataType?api.getVariableNameString()}", description = "${request.description! ""}", required = ${request.required?c}, schema = @Schema(description = "${request.contentObjects[0].description! ""}")) @Valid @RequestBody
${request.contentObjects[0].dataType} ${request.contentObjects[0].dataType?api.getVariableNameString()} <#if request?has_next>, </#if></#list></#if></@compress>) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
import com.sngular.api.generator.plugin.openapi.parameter.SpecFile;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.io.CleanupMode;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class OpenApiGeneratorJakartaTest {

@TempDir
@TempDir(cleanup = CleanupMode.NEVER)
static Path baseDir;

private static OpenApiGenerator openApiGenerator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@

import com.sngular.api.generator.plugin.exception.InvalidAPIException;
import com.sngular.api.generator.plugin.openapi.parameter.SpecFile;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.CleanupMode;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

@Slf4j
class OpenApiGeneratorTest {

@TempDir(cleanup = CleanupMode.NEVER)
@TempDir
static Path baseDir;

private static OpenApiGenerator openApiGenerator;
Expand Down Expand Up @@ -109,6 +110,7 @@ static Stream<Arguments> fileSpecToProcess() {
@MethodSource("fileSpecToProcess")
void processFileSpec(final String type, final List<SpecFile> specFileList, final Function<Path, Boolean> validation) {
openApiGenerator.processFileSpec(specFileList);
log.debug(baseDir.toAbsolutePath().toString());
Assertions.assertThat(validation.apply(baseDir)).isTrue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public interface TestApi {
*/

@Operation(
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
)
@RequestMapping(
method = RequestMethod.GET,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public interface TestApi {
*/

@Operation(
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
)
@RequestMapping(
method = RequestMethod.GET,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public interface TestApi {
*/

@Operation(
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
operationId = "testAdditionalProperties",
summary = "testAdditionalProperties",
tags = {"test"},
responses = {
@ApiResponse(responseCode = "200", description = "An object with additional properties", content = @Content(mediaType = "application/json", schema = @Schema(implementation = TestDTO.class)))
}
)
@RequestMapping(
method = RequestMethod.GET,
Expand Down
Loading

0 comments on commit 370ac0c

Please sign in to comment.