diff --git a/datamodel/openapi/openapi-generator/src/main/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverter.java b/datamodel/openapi/openapi-generator/src/main/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverter.java index 533d1c198..3e9ede305 100644 --- a/datamodel/openapi/openapi-generator/src/main/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverter.java +++ b/datamodel/openapi/openapi-generator/src/main/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverter.java @@ -95,10 +95,10 @@ public OperationsMap postProcessOperationsWithModels( private static void setGlobalSettings( @Nonnull final GenerationConfiguration configuration ) { if( configuration.isGenerateApis() ) { - GlobalSettings.setProperty(CodegenConstants.APIS, ""); + GlobalSettings.setProperty(CodegenConstants.APIS, getAllowedIds(configuration, "apisToGenerate")); } if( configuration.isGenerateModels() ) { - GlobalSettings.setProperty(CodegenConstants.MODELS, ""); + GlobalSettings.setProperty(CodegenConstants.MODELS, getAllowedIds(configuration, "modelsToGenerate")); } if( configuration.isDebugModels() ) { GlobalSettings.setProperty("debugModels", "true"); @@ -111,6 +111,15 @@ private static void setGlobalSettings( @Nonnull final GenerationConfiguration co GlobalSettings.setProperty(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString()); } + static String getAllowedIds( @Nonnull final GenerationConfiguration config, @Nonnull final String property ) + { + final var allowIds = config.getAdditionalProperties().get(property); + if( allowIds == null || allowIds.isBlank() ) { + return ""; + } + return String.join(",", allowIds.trim().split("\\W+")); + } + private static OpenAPI parseOpenApiSpec( @Nonnull final String inputSpecFile ) { final List authorizationValues = List.of(); diff --git a/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/DataModelGeneratorIntegrationTest.java b/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/DataModelGeneratorIntegrationTest.java index 0d2df3a24..67629831b 100644 --- a/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/DataModelGeneratorIntegrationTest.java +++ b/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/DataModelGeneratorIntegrationTest.java @@ -1,5 +1,8 @@ package com.sap.cloud.sdk.datamodel.openapi.generator; +import static java.util.Map.entry; +import static java.util.Map.ofEntries; + import static org.assertj.core.api.Assertions.assertThat; import java.nio.file.Files; @@ -94,14 +97,10 @@ private enum TestCase true, true, 6, - Map - .of( - "pojoBuilderMethodName", - "builder", - "pojoBuildMethodName", - "build", - "pojoConstructorVisibility", - "private")), + ofEntries( + entry("pojoBuilderMethodName", "builder"), + entry("pojoBuildMethodName", "build"), + entry("pojoConstructorVisibility", "private"))), REMOVE_OPERATION_ID_PREFIX( "remove-operation-id-prefix", "sodastore.json", @@ -111,14 +110,10 @@ private enum TestCase true, true, 6, - Map - .of( - "removeOperationIdPrefix", - "true", - "removeOperationIdPrefixDelimiter", - "\\.", - "removeOperationIdPrefixCount", - "3")), + ofEntries( + entry("removeOperationIdPrefix", "true"), + entry("removeOperationIdPrefixDelimiter", "\\."), + entry("removeOperationIdPrefixCount", "3"))), GENERATE_APIS( "generate-apis", "sodastore.yaml", @@ -128,7 +123,19 @@ private enum TestCase true, false, 7, - Map.of()); + Map.of()), + GENERATE_MODELS( + "generate-models", + "sodastore.yaml", + "test", + "test", + ApiMaturity.RELEASED, + true, + true, + 3, + ofEntries( + entry("apisToGenerate", "Default, NotExist"), + entry("modelsToGenerate", "Cola, Fanta, NotExist"))); final String testCaseName; final String inputSpecFileName; diff --git a/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverterTest.java b/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverterTest.java index 9ad40b528..1e8c1d181 100644 --- a/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverterTest.java +++ b/datamodel/openapi/openapi-generator/src/test/java/com/sap/cloud/sdk/datamodel/openapi/generator/GenerationConfigurationConverterTest.java @@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import com.google.common.collect.ImmutableMap; import com.sap.cloud.sdk.datamodel.openapi.generator.model.GenerationConfiguration; class GenerationConfigurationConverterTest @@ -35,6 +36,37 @@ void testCopyrightHeaderResolution() assertThat(resultNoHeader).isNull(); } + @Test + void testGetAllowedIds() + { + // assertion definition: given input -> expected output + final var assertions = + ImmutableMap + . builder() + .put("", "") // empty + .put("\n", "") // newline + .put("Foo", "Foo") // single + .put("Foo,Bar", "Foo,Bar") // list + .put("Foo;Bar", "Foo,Bar") // custom separator + .put("Foo Bar", "Foo,Bar") // space separator + .put("Foo \n Bar", "Foo,Bar") // new-line separator + .build(); + + // feed the assertion input arguments into the config + var configBuilder = GenerationConfiguration.builder(); + int i = 0; + for( String input : assertions.keySet() ) { + configBuilder.additionalProperty("property" + (i++), input); + } + var config = configBuilder.build(); + + // run the test + int j = 0; + for( String output : assertions.values() ) { + assertThat(GenerationConfigurationConverter.getAllowedIds(config, "property" + (j++))).isEqualTo(output); + } + } + private GenerationConfiguration.GenerationConfigurationBuilder createBasicConfig() { return GenerationConfiguration diff --git a/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/input/sodastore.yaml b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/input/sodastore.yaml new file mode 100644 index 000000000..615b573be --- /dev/null +++ b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/input/sodastore.yaml @@ -0,0 +1,58 @@ +openapi: 3.0.0 +info: + title: Soda Store API + version: 1.0.0 + description: API for managing sodas in a soda store +paths: + /sodas: + get: + summary: Get a list of all sodas + operationId: getSodas + responses: + '200': + description: A list of sodas + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OneOf' +components: + schemas: + ShouldNotBeGenerated: + oneOf: + - $ref: '#/components/schemas/Cola' + - $ref: '#/components/schemas/Fanta' + discriminator: + propertyName: sodaType + mapping: + Cola: '#/components/schemas/Cola' + Fanta: '#/components/schemas/Fanta' + OneOfWithDiscriminator: + oneOf: + - $ref: '#/components/schemas/Cola' + - $ref: '#/components/schemas/Fanta' + discriminator: + propertyName: sodaType + OneOf: + oneOf: + - $ref: '#/components/schemas/Cola' + - $ref: '#/components/schemas/Fanta' + AnyOf: + anyOf: + - $ref: '#/components/schemas/Cola' + - $ref: '#/components/schemas/Fanta' + AllOf: + allOf: + - $ref: '#/components/schemas/Cola' + - $ref: '#/components/schemas/Fanta' + Cola: + type: object + properties: + sodaType: + type: string + Fanta: + type: object + properties: + sodaType: + type: string diff --git a/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Cola.java b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Cola.java new file mode 100644 index 000000000..a2adbf686 --- /dev/null +++ b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Cola.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. + */ + +/* + * Soda Store API + * API for managing sodas in a soda store + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package test; + +import java.util.Objects; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Cola + */ +// CHECKSTYLE:OFF +public class Cola +// CHECKSTYLE:ON +{ + @JsonProperty("sodaType") + private String sodaType; + + @JsonAnySetter + @JsonAnyGetter + private final Map cloudSdkCustomFields = new LinkedHashMap<>(); + + /** + * Set the sodaType of this {@link Cola} instance and return the same instance. + * + * @param sodaType The sodaType of this {@link Cola} + * @return The same instance of this {@link Cola} class + */ + @Nonnull public Cola sodaType( @Nullable final String sodaType) { + this.sodaType = sodaType; + return this; + } + + /** + * Get sodaType + * @return sodaType The sodaType of this {@link Cola} instance. + */ + @Nonnull + public String getSodaType() { + return sodaType; + } + + /** + * Set the sodaType of this {@link Cola} instance. + * + * @param sodaType The sodaType of this {@link Cola} + */ + public void setSodaType( @Nullable final String sodaType) { + this.sodaType = sodaType; + } + + /** + * Get the names of the unrecognizable properties of the {@link Cola}. + * @return The set of properties names + */ + @JsonIgnore + @Nonnull + public Set getCustomFieldNames() { + return cloudSdkCustomFields.keySet(); + } + + /** + * Get the value of an unrecognizable property of this {@link Cola} instance. + * @param name The name of the property + * @return The value of the property + * @throws NoSuchElementException If no property with the given name could be found. + */ + @Nullable + public Object getCustomField( @Nonnull final String name ) throws NoSuchElementException { + if( !cloudSdkCustomFields.containsKey(name) ) { + throw new NoSuchElementException("Cola has no field with name '" + name + "'."); + } + return cloudSdkCustomFields.get(name); + } + + /** + * Set an unrecognizable property of this {@link Cola} instance. If the map previously contained a mapping + * for the key, the old value is replaced by the specified value. + * @param customFieldName The name of the property + * @param customFieldValue The value of the property + */ + @JsonIgnore + public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue ) + { + cloudSdkCustomFields.put(customFieldName, customFieldValue); + } + + + @Override + public boolean equals(@Nullable final java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Cola cola = (Cola) o; + return Objects.equals(this.cloudSdkCustomFields, cola.cloudSdkCustomFields) && + Objects.equals(this.sodaType, cola.sodaType); + } + + @Override + public int hashCode() { + return Objects.hash(sodaType, cloudSdkCustomFields); + } + + @Override + @Nonnull public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("class Cola {\n"); + sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n"); + cloudSdkCustomFields.forEach((k,v) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n")); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(final java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/DefaultApi.java b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/DefaultApi.java new file mode 100644 index 000000000..424ff2c43 --- /dev/null +++ b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/DefaultApi.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. + */ + +package test; + +import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException; +import com.sap.cloud.sdk.services.openapi.core.OpenApiResponse; +import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService; +import com.sap.cloud.sdk.services.openapi.apiclient.ApiClient; + +import test.OneOf; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import com.google.common.annotations.Beta; + +import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; + +/** + * Soda Store API in version 1.0.0. + * + * API for managing sodas in a soda store + */ +public class DefaultApi extends AbstractOpenApiService { + /** + * Instantiates this API class to invoke operations on the Soda Store API. + * + * @param httpDestination The destination that API should be used with + */ + public DefaultApi( @Nonnull final Destination httpDestination ) + { + super(httpDestination); + } + + /** + * Instantiates this API class to invoke operations on the Soda Store API based on a given {@link ApiClient}. + * + * @param apiClient + * ApiClient to invoke the API on + */ + @Beta + public DefaultApi( @Nonnull final ApiClient apiClient ) + { + super(apiClient); + } + + /** + *

Get a list of all sodas

+ *

+ *

200 - A list of sodas + * @return List<OneOf> + * @throws OpenApiRequestException if an error occurs while attempting to invoke the API + */ + @Nonnull + public List getSodas() throws OpenApiRequestException { + final Object localVarPostBody = null; + + final String localVarPath = UriComponentsBuilder.fromPath("/sodas").build().toUriString(); + + final MultiValueMap localVarQueryParams = new LinkedMultiValueMap(); + final HttpHeaders localVarHeaderParams = new HttpHeaders(); + final MultiValueMap localVarFormParams = new LinkedMultiValueMap(); + + final String[] localVarAccepts = { + "application/json" + }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { }; + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + final ParameterizedTypeReference> localVarReturnType = new ParameterizedTypeReference>() {}; + return apiClient.invokeAPI(localVarPath, HttpMethod.GET, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + } +} diff --git a/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Fanta.java b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Fanta.java new file mode 100644 index 000000000..c6359bba1 --- /dev/null +++ b/datamodel/openapi/openapi-generator/src/test/resources/DataModelGeneratorIntegrationTest/generate-models/output/test/Fanta.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved. + */ + +/* + * Soda Store API + * API for managing sodas in a soda store + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package test; + +import java.util.Objects; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Fanta + */ +// CHECKSTYLE:OFF +public class Fanta +// CHECKSTYLE:ON +{ + @JsonProperty("sodaType") + private String sodaType; + + @JsonAnySetter + @JsonAnyGetter + private final Map cloudSdkCustomFields = new LinkedHashMap<>(); + + /** + * Set the sodaType of this {@link Fanta} instance and return the same instance. + * + * @param sodaType The sodaType of this {@link Fanta} + * @return The same instance of this {@link Fanta} class + */ + @Nonnull public Fanta sodaType( @Nullable final String sodaType) { + this.sodaType = sodaType; + return this; + } + + /** + * Get sodaType + * @return sodaType The sodaType of this {@link Fanta} instance. + */ + @Nonnull + public String getSodaType() { + return sodaType; + } + + /** + * Set the sodaType of this {@link Fanta} instance. + * + * @param sodaType The sodaType of this {@link Fanta} + */ + public void setSodaType( @Nullable final String sodaType) { + this.sodaType = sodaType; + } + + /** + * Get the names of the unrecognizable properties of the {@link Fanta}. + * @return The set of properties names + */ + @JsonIgnore + @Nonnull + public Set getCustomFieldNames() { + return cloudSdkCustomFields.keySet(); + } + + /** + * Get the value of an unrecognizable property of this {@link Fanta} instance. + * @param name The name of the property + * @return The value of the property + * @throws NoSuchElementException If no property with the given name could be found. + */ + @Nullable + public Object getCustomField( @Nonnull final String name ) throws NoSuchElementException { + if( !cloudSdkCustomFields.containsKey(name) ) { + throw new NoSuchElementException("Fanta has no field with name '" + name + "'."); + } + return cloudSdkCustomFields.get(name); + } + + /** + * Set an unrecognizable property of this {@link Fanta} instance. If the map previously contained a mapping + * for the key, the old value is replaced by the specified value. + * @param customFieldName The name of the property + * @param customFieldValue The value of the property + */ + @JsonIgnore + public void setCustomField( @Nonnull String customFieldName, @Nullable Object customFieldValue ) + { + cloudSdkCustomFields.put(customFieldName, customFieldValue); + } + + + @Override + public boolean equals(@Nullable final java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Fanta fanta = (Fanta) o; + return Objects.equals(this.cloudSdkCustomFields, fanta.cloudSdkCustomFields) && + Objects.equals(this.sodaType, fanta.sodaType); + } + + @Override + public int hashCode() { + return Objects.hash(sodaType, cloudSdkCustomFields); + } + + @Override + @Nonnull public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("class Fanta {\n"); + sb.append(" sodaType: ").append(toIndentedString(sodaType)).append("\n"); + cloudSdkCustomFields.forEach((k,v) -> sb.append(" ").append(k).append(": ").append(toIndentedString(v)).append("\n")); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(final java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} +