Skip to content
Merged
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
1 change: 1 addition & 0 deletions datamodel/openapi/openapi-api-sample/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
<inputSpec>${project.basedir}/src/main/resources/sodastore.yaml</inputSpec>
<apiPackage>com.sap.cloud.sdk.datamodel.openapi.sample.api</apiPackage>
<modelPackage>com.sap.cloud.sdk.datamodel.openapi.sample.model</modelPackage>
<typeMappings>File=byte[]</typeMappings>
<additionalProperties>
<pojoBuilderMethodName>create</pojoBuilderMethodName>
<pojoBuildMethodName />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,68 @@ public SodasApi( @Nonnull final ApiClient apiClient )
super(apiClient);
}

/**
* <p>
* Download soda product data as binary
* </p>
* <p>
* </p>
* <p>
* <b>200</b> - Successful response
* <p>
* <b>404</b> - Soda product not found
*
* @param id
* ID of the soda product to download
* @return byte[]
* @throws OpenApiRequestException
* if an error occurs while attempting to invoke the API
*/
@Nonnull
public byte[] sodasDownloadIdGet( @Nonnull final Long id )
throws OpenApiRequestException
{
final Object localVarPostBody = null;

// verify the required parameter 'id' is set
if( id == null ) {
throw new OpenApiRequestException("Missing the required parameter 'id' when calling sodasDownloadIdGet");
}

// create path and map variables
final Map<String, Object> localVarPathParams = new HashMap<String, Object>();
localVarPathParams.put("id", id);
final String localVarPath =
UriComponentsBuilder.fromPath("/sodas/download/{id}").buildAndExpand(localVarPathParams).toUriString();

final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();

final String[] localVarAccepts = { "application/octet-stream" };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);

final String[] localVarAuthNames = new String[] { "apiKeyAuth", "bearerAuth" };

final ParameterizedTypeReference<byte[]> localVarReturnType = new ParameterizedTypeReference<byte[]>()
{
};
return apiClient
.invokeAPI(
localVarPath,
HttpMethod.GET,
localVarQueryParams,
localVarPostBody,
localVarHeaderParams,
localVarFormParams,
localVarAccept,
localVarContentType,
localVarAuthNames,
localVarReturnType);
}

/**
* <p>
* Get all soda products
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,29 @@ paths:
$ref: '#/components/schemas/SodaWithId'
'404':
description: Soda product not found
/sodas/download/{id}:
get:
summary: Download soda product data as binary
tags:
- Sodas
parameters:
- name: id
in: path
description: ID of the soda product to download
required: true
schema:
type: integer
format: int64
responses:
'200':
description: Successful response
content:
application/octet-stream:
schema:
type: string
format: binary
'404':
description: Soda product not found
/orders:
post:
summary: Create a new order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ void testUnexpectedAdditionalField()
assertThat(actual.getCustomField("unexpectedField")).asInstanceOf(InstanceOfAssertFactories.LIST).isEmpty();
}

@Test
void testBinaryResponse()
{
final byte[] binaryData = "binary file content".getBytes();
WireMock
.stubFor(
WireMock
.get(WireMock.urlMatching("/sodas/download/\\d+"))
.willReturn(
WireMock
.aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/octet-stream")
.withBody(binaryData)));

final byte[] result = sut.sodasDownloadIdGet(1L);
assertThat(result).isNotNull();
assertThat(result).isEqualTo(binaryData);
}

private void stub( String responseBody )
{
WireMock.stubFor(WireMock.get(WireMock.anyUrl()).willReturn(okJson(responseBody)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.sap.cloud.sdk.datamodel.openapi.generator;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
Expand Down Expand Up @@ -126,6 +131,18 @@ public class DataModelGeneratorMojo extends AbstractMojo
@Parameter( property = "openapi.generate.generateApis", defaultValue = "true" )
private boolean generateApis;

/**
* Type mappings to override OpenAPI specification types and the types used in your generated code.
*/
@Parameter( property = "openapi.generate.typeMappings" )
private List<String> typeMappings;

/**
* Import mappings to specify alternative imports statement to use for a given class name.
*/
@Parameter( property = "openapi.generate.importMappings" )
private List<String> importMappings;

/**
* Defines a list of additional properties that will be passed to the Java generator.
*/
Expand Down Expand Up @@ -189,6 +206,8 @@ Try<GenerationConfiguration> retrieveGenerationConfiguration()
.oneOfAnyOfGenerationEnabled(enableOneOfAnyOfGeneration)
.generateModels(generateModels)
.generateApis(generateApis)
.typeMappings(parseMapping(typeMappings))
.importMappings(parseMapping(importMappings))
.build());
}

Expand All @@ -198,4 +217,16 @@ void setOutputDirectory( final String outputDirectory )
this.outputDirectory = outputDirectory;
}

@Nonnull
private Map<String, String> parseMapping( @Nonnull final List<String> mappings )
{
return mappings
.stream()
.filter(Objects::nonNull)
.filter(line -> line.contains("="))
.map(line -> line.split("=", 2))
.map(parts -> new String[] { parts[0].trim(), parts[1].trim() })
.filter(parts -> !parts[0].isEmpty() && !parts[1].isEmpty())
.collect(Collectors.toMap(parts -> parts[0], parts -> parts[1]));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class DataModelGeneratorMojoUnitTest
RESOURCE_PATH + "/testInvocationWithUnexpectedApiMaturity/pom.xml";
private static final String ADDITIONAL_PROPERTIES_POM =
RESOURCE_PATH + "/testAdditionalPropertiesAndEnablingAnyOfOneOf/pom.xml";
private static final String MAPPINGS_EDGE_CASES_POM = RESOURCE_PATH + "/testMappingsEdgeCases/pom.xml";

@TempDir
File outputDirectory;
Expand All @@ -50,6 +51,11 @@ void testInvocationWithAllParameters( DataModelGeneratorMojo mojo )
assertThat(configuration.getApiPackage()).isEqualTo("com.sap.cloud.sdk.datamodel.rest.test.api");
assertThat(configuration.deleteOutputDirectory()).isTrue();
assertThat(configuration.isOneOfAnyOfGenerationEnabled()).isFalse();
assertThat(configuration.getTypeMappings())
.containsEntry("binary", "org.springframework.core.io.Resource")
.containsEntry("file", "org.springframework.core.io.Resource");
assertThat(configuration.getImportMappings())
.containsEntry("org.springframework.core.io.Resource", "org.springframework.core.io.Resource");

mojo.setOutputDirectory(outputDirectory.getAbsolutePath());

Expand All @@ -71,6 +77,8 @@ void testInvocationWithMandatoryParameters( DataModelGeneratorMojo mojo )
assertThat(configuration.getModelPackage()).isEqualTo("com.sap.cloud.sdk.datamodel.rest.test.model");
assertThat(configuration.getApiPackage()).isEqualTo("com.sap.cloud.sdk.datamodel.rest.test.api");
assertThat(configuration.deleteOutputDirectory()).isFalse();
assertThat(configuration.getTypeMappings()).isEmpty();
assertThat(configuration.getImportMappings()).isEmpty();

mojo.setOutputDirectory(outputDirectory.getAbsolutePath());

Expand Down Expand Up @@ -126,4 +134,21 @@ void testAdditionalPropertiesAndEnablingAnyOfOneOf( DataModelGeneratorMojo mojo

assertThat(mojo.retrieveGenerationConfiguration().get().isOneOfAnyOfGenerationEnabled()).isTrue();
}

@Test
@InjectMojo( goal = "generate", pom = MAPPINGS_EDGE_CASES_POM )
void testMappingsEdgeCases( DataModelGeneratorMojo mojo )
throws Throwable
{
final GenerationConfiguration configuration = mojo.retrieveGenerationConfiguration().get();

assertThat(configuration.getTypeMappings())
.hasSize(2) // Only valid mappings should remain
.containsEntry("File", "byte[]")
.containsEntry("binary", "org.springframework.core.io.Resource");

assertThat(configuration.getImportMappings())
.hasSize(1)
.containsEntry("Resource", "org.springframework.core.io.Resource");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@
<verbose>true</verbose>
<outputDirectory>output-directory</outputDirectory>
<deleteOutputDirectory>true</deleteOutputDirectory>
</configuration>
<typeMappings>
<typeMapping>binary=org.springframework.core.io.Resource</typeMapping>
<typeMapping>file=org.springframework.core.io.Resource</typeMapping>
</typeMappings>
<importMappings>
<importMapping>org.springframework.core.io.Resource=org.springframework.core.io.Resource</importMapping>
</importMappings>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>application</artifactId>
<version>5.25.0-SNAPSHOT</version>

<build>
<plugins>
<plugin>
<groupId>com.sap.cloud.sdk.datamodel</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<configuration>
<inputSpec>DataModelGeneratorMojoUnitTest/testMappingsEdgeCases/input/sodastore.yaml</inputSpec>
<apiPackage>com.sap.cloud.sdk.datamodel.rest.test.api</apiPackage>
<modelPackage>com.sap.cloud.sdk.datamodel.rest.test.model</modelPackage>
<apiMaturity>released</apiMaturity>
<outputDirectory>output-directory</outputDirectory>
<typeMappings>
<typeMapping>File=byte[]</typeMapping>
<typeMapping>binary = org.springframework.core.io.Resource</typeMapping>
<typeMapping>no-equals-sign</typeMapping>
<typeMapping>=missing-key</typeMapping>
<typeMapping>missing-value=</typeMapping>
<typeMapping>=</typeMapping>
<typeMapping></typeMapping><!-- Invalid: empty -->
</typeMappings>
<importMappings>
<importMapping>Resource=org.springframework.core.io.Resource</importMapping>
<importMapping>no-equals-sign</importMapping>
</importMappings>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ static ClientOptInput convertGenerationConfiguration(
config.setModelPackage(generationConfiguration.getModelPackage());
config.setTemplateDir(TEMPLATE_DIRECTORY);
config.additionalProperties().putAll(getAdditionalProperties(generationConfiguration));
config.typeMapping().putAll(generationConfiguration.getTypeMappings());
config.importMapping().putAll(generationConfiguration.getImportMappings());

final var openAPI = parseOpenApiSpec(inputSpecFile, generationConfiguration);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ public class GenerationConfiguration
@Builder.Default
boolean debugModels = false;

@Singular( ignoreNullCollections = true )
Map<String, String> typeMappings;

@Singular( ignoreNullCollections = true )
Map<String, String> importMappings;

/**
* Indicates whether to use the default SAP copyright header for generated files.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

import javax.annotation.Nullable;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.openapitools.codegen.ClientOptInput;

import com.sap.cloud.sdk.datamodel.openapi.generator.model.GenerationConfiguration;

Expand Down Expand Up @@ -57,4 +59,22 @@ private String getCopyrightHeaderFromConfig( final GenerationConfiguration confi
.get(GenerationConfigurationConverter.COPYRIGHT_PROPERTY_KEY);
return maybeHeader != null ? maybeHeader.toString() : null;
}

@Test
@SuppressWarnings( "deprecation" )
void testTypeMappingsAndImportMappingsAreApplied()
{
final Map<String, String> typeMappings =
Map.of("File", "byte[]", "binary", "org.springframework.core.io.Resource");
final Map<String, String> importMappings = Map.of("Resource", "org.springframework.core.io.Resource");

final GenerationConfiguration config =
createBasicConfig().typeMappings(typeMappings).importMappings(importMappings).build();

final ClientOptInput result =
GenerationConfigurationConverter.convertGenerationConfiguration(config, Paths.get(config.getInputSpec()));

assertThat(result.getConfig().typeMapping()).containsAllEntriesOf(typeMappings);
assertThat(result.getConfig().importMapping()).containsAllEntriesOf(importMappings);
}
}