Skip to content

Commit

Permalink
[kotlin] [bugfix] [maven-plugin]: prevent ClassCastException with boo…
Browse files Browse the repository at this point in the history
…lean config options (#4361)

* fix: prevent classcast exception during execution of openapi-generator-maven-plugin.

* style: revert styling to openapi defaults

* test: unit test coverage for handling boolean config options

* fix: replace option value with boolean, if it is a string literal boolean

* style: use data type long

* test: add maven testfile kotlin.xml to travis build

* test: runnable maven test of the kotlin generator
  • Loading branch information
janweinschenker authored and wing328 committed Nov 8, 2019
1 parent b0b0e2b commit f9af3c2
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 7 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ script:
# test maven plugin
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/java-client.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/multi-module/pom.xml
- mvn clean compile -f modules/openapi-generator-maven-plugin/examples/kotlin.xml
# test gradle plugin
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew buildGoSdk)
- (cd modules/openapi-generator-gradle-plugin/samples/local-spec && ./gradlew openApiGenerate)
Expand Down
237 changes: 237 additions & 0 deletions modules/openapi-generator-maven-plugin/examples/kotlin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>sample-project</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>sample-project</name>
<url>http://maven.apache.org</url>

<build>
<plugins>
<!-- activate the plugin -->
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>4.2.1-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<id>default</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>${project.basedir}/swagger.yaml</inputSpec>

<!-- target to generate java client code -->
<generatorName>kotlin</generatorName>

<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
you can use the following target: <generatorName>spring</generatorName> -->

<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>

</configuration>
</execution>
<execution>
<id>kotlin</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- specify the swagger yaml -->
<inputSpec>https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml
</inputSpec>

<!-- target to generate java client code -->
<generatorName>kotlin</generatorName>

<!-- hint: if you want to generate java server code, e.g. based on Spring Boot,
you can use the following target: <generatorName>spring</generatorName> -->

<!-- pass any necessary config options -->
<configOptions>
<serializableModel>true</serializableModel>
</configOptions>

<output>${project.build.directory}/generated-sources/kotlin</output>
<apiPackage>kotlintest.org.openapitools.client.api</apiPackage>
<modelPackage>kotlintest.org.openapitools.client.model</modelPackage>
<invokerPackage>kotlintest.org.openapitools.client</invokerPackage>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<proc>none</proc>
</configuration>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<jvmTarget>${kotlinJvmTarget}</jvmTarget>
<javacOptions/>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.build.directory}/generated-sources/kotlin/src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<pluginRepositories>
<pluginRepository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<!-- dependencies are needed for the client being generated -->

<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>

<!-- You can find the dependencies for the library configuation you chose by looking in JavaClientCodegen.
Then find the corresponding dependency on Maven Central, and set the versions in the property section below -->

<!-- HTTP client: jersey-client -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey-version}</version>
</dependency>

<!-- @Nullable annotation -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>

<!-- JSON processing: jackson -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind-nullable-version}</version>
</dependency>

<!-- Joda time: if you use it -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${jodatime-version}</version>
</dependency>

<!-- Base64 encoding that works in both JVM and Android -->
<dependency>
<groupId>com.brsanthu</groupId>
<artifactId>migbase64</artifactId>
<version>${migbase64.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>${moshi-kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.2</version>
</dependency>
</dependencies>

<properties>
<swagger-annotations-version>1.5.8</swagger-annotations-version>
<jersey-version>2.27</jersey-version>
<jackson-version>2.8.9</jackson-version>
<jackson-databind-nullable-version>0.2.0</jackson-databind-nullable-version>
<jodatime-version>2.7</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<junit-version>4.8.1</junit-version>
<kotlin.version>1.3.50</kotlin.version>
<kotlinJvmTarget>1.8</kotlinJvmTarget>
<moshi-kotlin.version>1.8.0</moshi-kotlin.version>
<migbase64.version>2.2</migbase64.version>
</properties>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -434,19 +434,19 @@ public void processOpts() {
}

if (additionalProperties.containsKey(CodegenConstants.SERIALIZABLE_MODEL)) {
this.setSerializableModel(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.SERIALIZABLE_MODEL)));
this.setSerializableModel(getBooleanOption(CodegenConstants.SERIALIZABLE_MODEL));
} else {
additionalProperties.put(CodegenConstants.SERIALIZABLE_MODEL, serializableModel);
}

if (additionalProperties.containsKey(CodegenConstants.PARCELIZE_MODELS)) {
this.setParcelizeModels(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.PARCELIZE_MODELS)));
this.setParcelizeModels(getBooleanOption(CodegenConstants.PARCELIZE_MODELS));
} else {
additionalProperties.put(CodegenConstants.PARCELIZE_MODELS, parcelizeModels);
}

if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
this.setNonPublicApi(Boolean.valueOf((String) additionalProperties.get(CodegenConstants.NON_PUBLIC_API)));
this.setNonPublicApi(getBooleanOption(CodegenConstants.NON_PUBLIC_API));
} else {
additionalProperties.put(CodegenConstants.NON_PUBLIC_API, nonPublicApi);
}
Expand All @@ -458,6 +458,18 @@ public void processOpts() {
additionalProperties.put("modelDocPath", modelDocPath);
}

private boolean getBooleanOption(String key) {
final Object booleanValue = additionalProperties.get(key);
Boolean result = Boolean.FALSE;
if (booleanValue instanceof Boolean) {
result = (Boolean) booleanValue;
} else if (booleanValue instanceof String) {
result = Boolean.parseBoolean((String) booleanValue);
}
additionalProperties.put(key, result);
return result;
}

public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
Expand Down Expand Up @@ -501,7 +513,7 @@ public boolean isSerializableModel() {
public void setSerializableModel(boolean serializableModel) {
this.serializableModel = serializableModel;
}

public boolean nonPublicApi() {
return nonPublicApi;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.openapitools.codegen.kotlin;

import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
import org.testng.Assert;
Expand Down Expand Up @@ -53,7 +54,7 @@ public void pascalCaseEnumConverter() {
}

@Test
public void toEnumValue(){
public void toEnumValue() {
assertEquals(codegen.toEnumValue("1", "kotlin.Int"), "1");
assertEquals(codegen.toEnumValue("1", "kotlin.Double"), "1.0");
assertEquals(codegen.toEnumValue("1.3", "kotlin.Double"), "1.3");
Expand Down Expand Up @@ -81,14 +82,14 @@ public String getHelp() {
}

@Test
public void isDataTypeString(){
public void isDataTypeString() {
assertFalse(codegen.isDataTypeString("kotlin.Int"));
assertTrue(codegen.isDataTypeString("kotlin.String"));
assertTrue(codegen.isDataTypeString("String"));
}

@Test
public void toModelNameShouldUseProvidedMapping() {
public void toModelNameShouldUseProvidedMapping() {
codegen.importMapping().put("json_myclass", "com.test.MyClass");
assertEquals("com.test.MyClass", codegen.toModelName("json_myclass"));
}
Expand Down Expand Up @@ -155,5 +156,45 @@ public void apiTestFileFolder() {
Assert.assertEquals(codegen.apiTestFileFolder(), "/User/open/api/tools/test/folder/org/openapitools/codegen/api".replace('/', File.separatorChar));
}

@Test
public void processOptsBooleanTrueFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "true");
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanTrueFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, true);
codegen.processOpts();
Assert.assertTrue((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromString() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "false");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromBoolean() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, false);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromGarbage() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, "blibb");
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}

@Test
public void processOptsBooleanFalseFromNumeric() {
codegen.additionalProperties().put(CodegenConstants.SERIALIZABLE_MODEL, 42L);
codegen.processOpts();
Assert.assertFalse((boolean) codegen.additionalProperties().get(CodegenConstants.SERIALIZABLE_MODEL));
}
}

0 comments on commit f9af3c2

Please sign in to comment.