Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[kotlin] [bugfix] [maven-plugin]: prevent ClassCastException with boolean config options #4361

Merged
merged 7 commits into from
Nov 8, 2019
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));
}
}