diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache index 7335ab00f..95ebe98d7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache @@ -131,8 +131,12 @@ public class {{classname}} { final MultiValueMap localVarCookieParams = new LinkedMultiValueMap(); final MultiValueMap localVarFormParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} - {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + {{#queryParams}}{{#isExplode}}{{#hasVars}} + if ({{paramName}} != null) { + {{#vars}} localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}.{{getter}}())); + {{/vars}}}{{/hasVars}}{{^hasVars}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/hasVars}}{{/isExplode}}{{^isExplode}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + {{/isExplode}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatCommonJavaCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatCommonJavaCodeGenTests.java index 428cb342a..38873b077 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatCommonJavaCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatCommonJavaCodeGenTests.java @@ -1,5 +1,6 @@ package com.backbase.oss.codegen.java; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -19,10 +20,12 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; +import java.util.stream.Collectors; import lombok.SneakyThrows; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.openapitools.codegen.ClientOptInput; @@ -49,6 +52,42 @@ void shouldGenerateArrayField(String containerDefaultToNull) { generateAndAssert(springCodeGen(), containerDefaultToNull); } + @Test + void shouldExplodePojoQueryParam() throws IOException { + + BoatJavaCodeGen codegen = javaCodeGenWithLib(RESTTEMPLATE); + + var input = new File("src/test/resources/boat-spring/openapi.yaml"); + var outputDir = TEST_OUTPUT + "/shouldExplodePojoQueryParam"; + + codegen.setInputSpec(input.getAbsolutePath()); + codegen.setOutputDir(outputDir); + + OpenAPI openApiInput = new OpenAPIParser() + .readLocation(input.getAbsolutePath(), null, new ParseOptions()) + .getOpenAPI(); + var clientOptInput = new ClientOptInput(); + clientOptInput.config(codegen); + clientOptInput.openAPI(openApiInput); + + List files = new DefaultGenerator().opts(clientOptInput).generate(); + + File pojosInQueryApi = files.stream() + .filter(it -> it.getName().equals("PojosInQueryApi.java")) + .findFirst() + .orElseThrow(); + + List lines = Files.readAllLines(pojosInQueryApi.toPath()).stream() + .map(String::trim) + .collect(Collectors.toList()); + + assertThat(lines) + .contains("public ResponseEntity getWithPojosInQueryWithHttpInfo(String simpleParam, MyPojo pojoParam) throws RestClientException {") + .contains("localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, \"simpleParam\", simpleParam));") + .contains("localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, \"field1\", pojoParam.getField1()));") + .contains("localVarQueryParams.putAll(apiClient.parameterToMultiValueMap(null, \"field2\", pojoParam.getField2()));"); + } + private static BoatJavaCodeGen javaCodeGenWithLib(String library) { var codeGen = new BoatJavaCodeGen(); codeGen.setLibrary(library); @@ -115,7 +154,7 @@ private void assertVariableDeclarator(CompilationUnit requestClass, String field .findAll(FieldDeclaration.class) .stream() .flatMap(field -> field.getChildNodes().stream()) - .filter(node -> node instanceof VariableDeclarator) + .filter(VariableDeclarator.class::isInstance) .map(VariableDeclarator.class::cast) .filter(declarator -> declarator.getName().getIdentifier().equals(fieldName)) .findFirst() diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java index 412910480..1dd8c6215 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java @@ -1,11 +1,30 @@ package com.backbase.oss.codegen.java; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.CREATE_API_COMPONENT; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.REST_TEMPLATE_BEAN_NAME; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.USE_CLASS_LEVEL_BEAN_VALIDATION; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.USE_DEFAULT_API_CLIENT; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.USE_JACKSON_CONVERSION; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.USE_PROTECTED_FIELDS; +import static com.backbase.oss.codegen.java.BoatJavaCodeGen.USE_WITH_MODIFIERS; +import static java.util.stream.Collectors.groupingBy; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.TypeDeclaration; import io.swagger.parser.OpenAPIParser; import io.swagger.v3.parser.core.models.ParseOptions; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; +import java.util.function.Function; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -13,18 +32,6 @@ import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.DefaultGenerator; -import java.io.File; -import java.io.FileNotFoundException; -import java.util.function.Function; -import java.util.List; -import java.util.Map; - -import static com.backbase.oss.codegen.java.BoatJavaCodeGen.*; -import static java.util.stream.Collectors.groupingBy; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.jupiter.api.Assertions.assertEquals; - class BoatJavaCodeGenTests { static final String PROP_BASE = BoatJavaCodeGenTests.class.getSimpleName() + "."; @@ -115,10 +122,10 @@ void processOptsUseProtectedFields() { @ParameterizedTest @ValueSource(booleans = {true, false}) - void shouldHonourGenerateComponentAnnotation(boolean generate) throws InterruptedException, FileNotFoundException { + void shouldHonourGenerateComponentAnnotation(boolean generate) throws FileNotFoundException { var input = new File("src/test/resources/boat-spring/openapi.yaml"); - var output = TEST_OUTPUT + "/shouldNotGenerateComponentAnnotation/" + String.valueOf(generate); + var output = TEST_OUTPUT + "/shouldNotGenerateComponentAnnotation/" + generate; final BoatJavaCodeGen gen = new BoatJavaCodeGen(); gen.setOutputDir(output); @@ -162,10 +169,10 @@ void shouldHonourGenerateComponentAnnotation(boolean generate) throws Interrupte @ParameterizedTest @ValueSource(booleans = {true, false}) - void shouldHonourBeanValidationOption(boolean useBeanValidation) throws InterruptedException, FileNotFoundException { + void shouldHonourBeanValidationOption(boolean useBeanValidation) throws FileNotFoundException { var input = new File("src/test/resources/boat-spring/openapi.yaml"); - var output = TEST_OUTPUT + "/shouldHonourBeanValidationOption/" + String.valueOf(useBeanValidation); + var output = TEST_OUTPUT + "/shouldHonourBeanValidationOption/" + useBeanValidation; final BoatJavaCodeGen gen = new BoatJavaCodeGen(); gen.setOutputDir(output); diff --git a/boat-scaffold/src/test/resources/boat-spring/openapi.yaml b/boat-scaffold/src/test/resources/boat-spring/openapi.yaml index 8b4b1972a..b083c78cb 100644 --- a/boat-scaffold/src/test/resources/boat-spring/openapi.yaml +++ b/boat-scaffold/src/test/resources/boat-spring/openapi.yaml @@ -188,8 +188,49 @@ paths: format: number number-typed-value: type: number + + /use-pojo-as-query-param: + get: + tags: + - pojosInQuery + operationId: getWithPojosInQuery + parameters: + - name: simpleParam + in: query + required: true + style: form + explode: true + schema: + type: string + - name: pojoParam + in: query + required: true + style: form + explode: true + schema: + $ref: "#/components/schemas/MyPojo" + responses: + "200": + description: OK + components: schemas: + MyPojo: + required: + - field1 + - field2 + type: object + properties: + field1: + maxLength: 32 + minLength: 1 + pattern: ^\S.*$ + type: string + field2: + maxLength: 50 + minLength: 1 + pattern: ^\S.*$ + type: string Additions: title: Additions type: object