diff --git a/.github/workflows/samples-kotlin-client.yaml b/.github/workflows/samples-kotlin-client.yaml
index c83dac3cfd2..618d80fe9a0 100644
--- a/.github/workflows/samples-kotlin-client.yaml
+++ b/.github/workflows/samples-kotlin-client.yaml
@@ -65,6 +65,7 @@ jobs:
- samples/client/echo_api/kotlin-jvm-spring-3-restclient
- samples/client/petstore/kotlin-name-parameter-mappings
- samples/client/others/kotlin-jvm-okhttp-parameter-tests
+ - samples/client/others/kotlin-jvm-okhttp-path-comments
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
diff --git a/bin/configs/kotlin-jvm-okhttp-path-comments.yaml b/bin/configs/kotlin-jvm-okhttp-path-comments.yaml
new file mode 100644
index 00000000000..401917ced41
--- /dev/null
+++ b/bin/configs/kotlin-jvm-okhttp-path-comments.yaml
@@ -0,0 +1,8 @@
+generatorName: kotlin
+outputDir: samples/client/others/kotlin-jvm-okhttp-path-comments
+library: jvm-okhttp4
+inputSpec: modules/openapi-generator/src/test/resources/3_0/kotlin/issue20618-path-comments.yaml
+templateDir: modules/openapi-generator/src/main/resources/kotlin-client
+additionalProperties:
+ artifactId: kotlin-petstore-okhttp4-path-comments
+
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
index 43393ef8827..fab6b3e5d83 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinClientCodegen.java
@@ -40,6 +40,35 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import com.samskivert.mustache.Mustache;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+import org.openapitools.codegen.CliOption;
+import org.openapitools.codegen.CodegenConstants;
+import org.openapitools.codegen.CodegenModel;
+import org.openapitools.codegen.CodegenOperation;
+import org.openapitools.codegen.CodegenParameter;
+import org.openapitools.codegen.CodegenProperty;
+import org.openapitools.codegen.CodegenType;
+import org.openapitools.codegen.SupportingFile;
+import org.openapitools.codegen.VendorExtension;
+import org.openapitools.codegen.meta.features.ClientModificationFeature;
+import org.openapitools.codegen.meta.features.DocumentationFeature;
+import org.openapitools.codegen.meta.features.GlobalFeature;
+import org.openapitools.codegen.meta.features.ParameterFeature;
+import org.openapitools.codegen.meta.features.SchemaSupportFeature;
+import org.openapitools.codegen.meta.features.SecurityFeature;
+import org.openapitools.codegen.meta.features.WireFormatFeature;
+import org.openapitools.codegen.model.ModelMap;
+import org.openapitools.codegen.model.ModelsMap;
+import org.openapitools.codegen.model.OperationMap;
+import org.openapitools.codegen.model.OperationsMap;
+import org.openapitools.codegen.templating.mustache.ReplaceAllLambda;
+import org.openapitools.codegen.utils.ProcessUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import static java.util.Collections.sort;
public class KotlinClientCodegen extends AbstractKotlinCodegen {
@@ -536,6 +565,10 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
}
writer.write(content);
});
+ // When a path is added to a Javadoc, if it ends with a `/*` is will cause a compiler error
+ // as the parser interrupts that as a start of a multiline comment.
+ // We replace paths like `/v1/foo/*` with `/v1/foo/<*>` to avoid this
+ additionalProperties.put("sanitizePathComment", new ReplaceAllLambda("\\/\\*", "/<*>"));
}
private void processDateLibrary() {
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-ktor/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-ktor/api.mustache
index 5d00194376d..de8c6a87447 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-ktor/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-ktor/api.mustache
@@ -43,7 +43,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
{{#operation}}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}} * @param {{{paramName}}} {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache
index bf37a51fd43..3569367be6e 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-okhttp/api.mustache
@@ -123,7 +123,7 @@ import {{packageName}}.infrastructure.toMultiValue
{{/isEnum}}
{{/allParams}}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
@@ -161,7 +161,7 @@ import {{packageName}}.infrastructure.toMultiValue
}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
index ab2dc653c42..e6ad5f06d19 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustache
@@ -131,7 +131,7 @@ import okhttp3.MultipartBody
{{/isEnum}}
{{/allParams}}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
* Responses:{{#responses}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-vertx/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-vertx/api.mustache
index 65aa43a4f54..ceb094109c5 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-vertx/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-vertx/api.mustache
@@ -88,7 +88,7 @@ import {{packageName}}.infrastructure.*
{{/isEnum}}
{{/allParams}}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
@@ -123,7 +123,7 @@ import {{packageName}}.infrastructure.*
}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
diff --git a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-volley/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-volley/api.mustache
index cea755a0f70..03b5967ef63 100644
--- a/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-volley/api.mustache
+++ b/modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-volley/api.mustache
@@ -37,7 +37,7 @@ import {{packageName}}.infrastructure.CollectionFormats.*
{{#operation}}
/**
- * {{{httpMethod}}} {{{path}}}
+ * {{{httpMethod}}} {{#sanitizePathComment}}{{{path}}}{{/sanitizePathComment}}
* {{summary}}
* {{notes}}
{{#allParams}}* @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}}
diff --git a/modules/openapi-generator/src/test/resources/3_0/kotlin/issue20618-path-comments.yaml b/modules/openapi-generator/src/test/resources/3_0/kotlin/issue20618-path-comments.yaml
new file mode 100644
index 00000000000..5f2d74a525f
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/kotlin/issue20618-path-comments.yaml
@@ -0,0 +1,41 @@
+# See: https://github.com/OpenAPITools/openapi-generator/pull/20618#issuecomment-2690874645
+openapi: 3.0.0
+servers:
+ - url: 'https://example.org/v1'
+info:
+ description: >-
+ Example created
+ version: 1.0.0
+ title: OpenAPI Stuff API created to reproduce issue
+ license:
+ name: Apache-2.0
+ url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
+tags:
+ - name: stuff
+ description: All about the stuff
+security:
+ - bearerAuth: []
+paths:
+ /foo/*:
+ get:
+ tags:
+ - stuff
+ summary: Finds stuff
+ description: Finds stuff
+ operationId: findStuff
+ responses:
+ '200':
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ id:
+ type: string
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator-ignore b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/FILES b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/FILES
new file mode 100644
index 00000000000..45658fb584c
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/FILES
@@ -0,0 +1,28 @@
+README.md
+build.gradle
+docs/FindStuff200Response.md
+docs/StuffApi.md
+gradle/wrapper/gradle-wrapper.jar
+gradle/wrapper/gradle-wrapper.properties
+gradlew
+gradlew.bat
+settings.gradle
+src/main/kotlin/org/openapitools/client/apis/StuffApi.kt
+src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt
+src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt
+src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt
+src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt
+src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt
+src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt
+src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt
+src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt
+src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt
+src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt
+src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt
+src/main/kotlin/org/openapitools/client/models/FindStuff200Response.kt
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/VERSION b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/VERSION
new file mode 100644
index 00000000000..96cfbb19ae2
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.13.0-SNAPSHOT
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/README.md b/samples/client/others/kotlin-jvm-okhttp-path-comments/README.md
new file mode 100644
index 00000000000..06a38d0c547
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/README.md
@@ -0,0 +1,66 @@
+# org.openapitools.client - Kotlin client library for OpenAPI Stuff API created to reproduce issue
+
+Example created
+
+## Overview
+This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client.
+
+- API version: 1.0.0
+- Package version:
+- Generator version: 7.13.0-SNAPSHOT
+- Build package: org.openapitools.codegen.languages.KotlinClientCodegen
+
+## Requires
+
+* Kotlin 1.7.21
+* Gradle 7.5
+
+## Build
+
+First, create the gradle wrapper script:
+
+```
+gradle wrapper
+```
+
+Then, run:
+
+```
+./gradlew check assemble
+```
+
+This runs all tests and packages the library.
+
+## Features/Implementation Notes
+
+* Supports JSON inputs/outputs, File inputs, and Form inputs.
+* Supports collection formats for query parameters: csv, tsv, ssv, pipes.
+* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions.
+* Implementation of ApiClient is intended to reduce method counts, specifically to benefit Android targets.
+
+
+## Documentation for API Endpoints
+
+All URIs are relative to *https://example.org/v1*
+
+| Class | Method | HTTP request | Description |
+| ------------ | ------------- | ------------- | ------------- |
+| *StuffApi* | [**findStuff**](docs/StuffApi.md#findstuff) | **GET** /foo/* | Finds stuff |
+
+
+
+## Documentation for Models
+
+ - [org.openapitools.client.models.FindStuff200Response](docs/FindStuff200Response.md)
+
+
+
+## Documentation for Authorization
+
+
+Authentication schemes defined for the API:
+
+### bearerAuth
+
+- **Type**: HTTP Bearer Token authentication (JWT)
+
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/build.gradle b/samples/client/others/kotlin-jvm-okhttp-path-comments/build.gradle
new file mode 100644
index 00000000000..ae12ac6e144
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/build.gradle
@@ -0,0 +1,62 @@
+group 'org.openapitools'
+version '1.0.0'
+
+wrapper {
+ gradleVersion = '8.7'
+ distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
+}
+
+buildscript {
+ ext.kotlin_version = '1.9.23'
+ ext.spotless_version = "6.25.0"
+
+ repositories {
+ maven { url "https://repo1.maven.org/maven2" }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotless_version"
+ }
+}
+
+apply plugin: 'kotlin'
+apply plugin: 'maven-publish'
+apply plugin: 'com.diffplug.spotless'
+
+repositories {
+ maven { url "https://repo1.maven.org/maven2" }
+}
+
+// Use spotless plugin to automatically format code, remove unused import, etc
+// To apply changes directly to the file, run `gradlew spotlessApply`
+// Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle
+spotless {
+ // comment out below to run spotless as part of the `check` task
+ enforceCheck false
+
+ format 'misc', {
+ // define the files (e.g. '*.gradle', '*.md') to apply `misc` to
+ target '.gitignore'
+
+ // define the steps to apply to those files
+ trimTrailingWhitespace()
+ indentWithSpaces() // Takes an integer argument if you don't like 4
+ endWithNewline()
+ }
+ kotlin {
+ ktfmt()
+ }
+}
+
+test {
+ useJUnitPlatform()
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
+ implementation "com.squareup.moshi:moshi-kotlin:1.15.1"
+ implementation "com.squareup.moshi:moshi-adapters:1.15.1"
+ implementation "com.squareup.okhttp3:okhttp:4.12.0"
+ testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2"
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/FindStuff200Response.md b/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/FindStuff200Response.md
new file mode 100644
index 00000000000..8e59a9bb50c
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/FindStuff200Response.md
@@ -0,0 +1,10 @@
+
+# FindStuff200Response
+
+## Properties
+| Name | Type | Description | Notes |
+| ------------ | ------------- | ------------- | ------------- |
+| **id** | **kotlin.String** | | [optional] |
+
+
+
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/StuffApi.md b/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/StuffApi.md
new file mode 100644
index 00000000000..5208c69e8d4
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/docs/StuffApi.md
@@ -0,0 +1,54 @@
+# StuffApi
+
+All URIs are relative to *https://example.org/v1*
+
+| Method | HTTP request | Description |
+| ------------- | ------------- | ------------- |
+| [**findStuff**](StuffApi.md#findStuff) | **GET** /foo/* | Finds stuff |
+
+
+
+# **findStuff**
+> FindStuff200Response findStuff()
+
+Finds stuff
+
+Finds stuff
+
+### Example
+```kotlin
+// Import classes:
+//import org.openapitools.client.infrastructure.*
+//import org.openapitools.client.models.*
+
+val apiInstance = StuffApi()
+try {
+ val result : FindStuff200Response = apiInstance.findStuff()
+ println(result)
+} catch (e: ClientException) {
+ println("4xx response calling StuffApi#findStuff")
+ e.printStackTrace()
+} catch (e: ServerException) {
+ println("5xx response calling StuffApi#findStuff")
+ e.printStackTrace()
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+[**FindStuff200Response**](FindStuff200Response.md)
+
+### Authorization
+
+
+Configure bearerAuth:
+ ApiClient.accessToken = ""
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.jar b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000000..d64cd491770
Binary files /dev/null and b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.properties b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000000..e7646dead06
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew
new file mode 100644
index 00000000000..9d0ce634cb1
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+[ -h "$app_path" ]
+do
+ls=$( ls -ld "$app_path" )
+link=${ls#*' -> '}
+case $link in #(
+/*) app_path=$link ;; #(
+*) app_path=$APP_HOME$link ;;
+esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+echo "$*"
+} >&2
+
+die () {
+echo
+echo "$*"
+echo
+exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+CYGWIN* ) cygwin=true ;; #(
+Darwin* ) darwin=true ;; #(
+MSYS* | MINGW* ) msys=true ;; #(
+NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+# IBM's JDK on AIX uses strange locations for the executables
+JAVACMD=$JAVA_HOME/jre/sh/java
+else
+JAVACMD=$JAVA_HOME/bin/java
+fi
+if [ ! -x "$JAVACMD" ] ; then
+die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+else
+JAVACMD=java
+if ! command -v java >/dev/null 2>&1
+then
+die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+case $MAX_FD in #(
+max*)
+# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+# shellcheck disable=SC2039,SC3045
+MAX_FD=$( ulimit -H -n ) ||
+warn "Could not query maximum file descriptor limit"
+esac
+case $MAX_FD in #(
+'' | soft) :;; #(
+*)
+# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+# shellcheck disable=SC2039,SC3045
+ulimit -n "$MAX_FD" ||
+warn "Could not set maximum file descriptor limit to $MAX_FD"
+esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+# Now convert the arguments - kludge to limit ourselves to /bin/sh
+for arg do
+if
+case $arg in #(
+-*) false ;; # don't mess with options #(
+/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+[ -e "$t" ] ;; #(
+*) false ;;
+esac
+then
+arg=$( cygpath --path --ignore --mixed "$arg" )
+fi
+# Roll the args list around exactly as many times as the number of
+# args, so each arg winds up back in the position where it started, but
+# possibly modified.
+#
+# NB: a `for` loop captures its iteration list before it begins, so
+# changing the positional parameters here affects neither the number of
+# iterations, nor the values presented in `arg`.
+shift # remove old arg
+set -- "$@" "$arg" # push replacement arg
+done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+"-Dorg.gradle.appname=$APP_BASE_NAME" \
+-classpath "$CLASSPATH" \
+org.gradle.wrapper.GradleWrapperMain \
+"$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+xargs -n1 |
+sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+tr '\n' ' '
+)" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew.bat b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew.bat
new file mode 100644
index 00000000000..107acd32c4e
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/settings.gradle b/samples/client/others/kotlin-jvm-okhttp-path-comments/settings.gradle
new file mode 100644
index 00000000000..7b619d0025d
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'kotlin-petstore-okhttp4-path-comments'
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/apis/StuffApi.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/apis/StuffApi.kt
new file mode 100644
index 00000000000..83e5fc14592
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/apis/StuffApi.kt
@@ -0,0 +1,121 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.apis
+
+import java.io.IOException
+import okhttp3.Call
+import okhttp3.HttpUrl
+
+import org.openapitools.client.models.FindStuff200Response
+
+import com.squareup.moshi.Json
+
+import org.openapitools.client.infrastructure.ApiClient
+import org.openapitools.client.infrastructure.ApiResponse
+import org.openapitools.client.infrastructure.ClientException
+import org.openapitools.client.infrastructure.ClientError
+import org.openapitools.client.infrastructure.ServerException
+import org.openapitools.client.infrastructure.ServerError
+import org.openapitools.client.infrastructure.MultiValueMap
+import org.openapitools.client.infrastructure.PartConfig
+import org.openapitools.client.infrastructure.RequestConfig
+import org.openapitools.client.infrastructure.RequestMethod
+import org.openapitools.client.infrastructure.ResponseType
+import org.openapitools.client.infrastructure.Success
+import org.openapitools.client.infrastructure.toMultiValue
+
+class StuffApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) {
+ companion object {
+ @JvmStatic
+ val defaultBasePath: String by lazy {
+ System.getProperties().getProperty(ApiClient.baseUrlKey, "https://example.org/v1")
+ }
+ }
+
+ /**
+ * GET /foo/<*>
+ * Finds stuff
+ * Finds stuff
+ * @return FindStuff200Response
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun findStuff() : FindStuff200Response {
+ val localVarResponse = findStuffWithHttpInfo()
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as FindStuff200Response
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * GET /foo/<*>
+ * Finds stuff
+ * Finds stuff
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun findStuffWithHttpInfo() : ApiResponse {
+ val localVariableConfig = findStuffRequestConfig()
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation findStuff
+ *
+ * @return RequestConfig
+ */
+ fun findStuffRequestConfig() : RequestConfig {
+ val localVariableBody = null
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.GET,
+ path = "/foo/*",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = true,
+ body = localVariableBody
+ )
+ }
+
+
+ private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String =
+ HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0]
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt
new file mode 100644
index 00000000000..7fe8da46837
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt
@@ -0,0 +1,23 @@
+package org.openapitools.client.infrastructure
+
+typealias MultiValueMap = MutableMap>
+
+fun collectionDelimiter(collectionFormat: String): String = when(collectionFormat) {
+ "csv" -> ","
+ "tsv" -> "\t"
+ "pipe" -> "|"
+ "space" -> " "
+ else -> ""
+}
+
+val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" }
+
+fun toMultiValue(items: Array, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List
+ = toMultiValue(items.asIterable(), collectionFormat, map)
+
+fun toMultiValue(items: Iterable, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List {
+ return when(collectionFormat) {
+ "multi" -> items.map(map)
+ else -> listOf(items.joinToString(separator = collectionDelimiter(collectionFormat), transform = map))
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt
new file mode 100644
index 00000000000..ce4162fa669
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt
@@ -0,0 +1,368 @@
+package org.openapitools.client.infrastructure
+
+import okhttp3.OkHttpClient
+import okhttp3.RequestBody
+import okhttp3.RequestBody.Companion.asRequestBody
+import okhttp3.RequestBody.Companion.toRequestBody
+import okhttp3.FormBody
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.ResponseBody
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.Request
+import okhttp3.Headers
+import okhttp3.Headers.Builder
+import okhttp3.Headers.Companion.toHeaders
+import okhttp3.MultipartBody
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.Response
+import java.io.BufferedWriter
+import java.io.File
+import java.io.FileWriter
+import java.io.IOException
+import java.net.URLConnection
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.LocalTime
+import java.time.OffsetDateTime
+import java.time.OffsetTime
+import java.util.Locale
+import java.util.regex.Pattern
+import com.squareup.moshi.adapter
+
+val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody()
+
+open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClient) {
+ companion object {
+ protected const val ContentType: String = "Content-Type"
+ protected const val Accept: String = "Accept"
+ protected const val Authorization: String = "Authorization"
+ protected const val JsonMediaType: String = "application/json"
+ protected const val FormDataMediaType: String = "multipart/form-data"
+ protected const val FormUrlEncMediaType: String = "application/x-www-form-urlencoded"
+ protected const val XmlMediaType: String = "application/xml"
+ protected const val OctetMediaType: String = "application/octet-stream"
+ protected const val TextMediaType: String = "text/plain"
+
+ val apiKey: MutableMap = mutableMapOf()
+ val apiKeyPrefix: MutableMap = mutableMapOf()
+ var username: String? = null
+ var password: String? = null
+ var accessToken: String? = null
+ const val baseUrlKey: String = "org.openapitools.client.baseUrl"
+
+ @JvmStatic
+ val defaultClient: OkHttpClient by lazy {
+ builder.build()
+ }
+
+ @JvmStatic
+ val builder: OkHttpClient.Builder = OkHttpClient.Builder()
+ }
+
+ /**
+ * Guess Content-Type header from the given byteArray (defaults to "application/octet-stream").
+ *
+ * @param byteArray The given file
+ * @return The guessed Content-Type
+ */
+ protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String {
+ val contentType = try {
+ URLConnection.guessContentTypeFromStream(byteArray.inputStream())
+ } catch (io: IOException) {
+ "application/octet-stream"
+ }
+ return contentType
+ }
+
+ /**
+ * Guess Content-Type header from the given file (defaults to "application/octet-stream").
+ *
+ * @param file The given file
+ * @return The guessed Content-Type
+ */
+ protected fun guessContentTypeFromFile(file: File): String {
+ val contentType = URLConnection.guessContentTypeFromName(file.name)
+ return contentType ?: "application/octet-stream"
+ }
+
+ /**
+ * Adds a File to a MultipartBody.Builder
+ * Defined a helper in the requestBody method to not duplicate code
+ * It will be used when the content is a FormDataMediaType and the body of the PartConfig is a File
+ *
+ * @param name The field name to add in the request
+ * @param headers The headers that are in the PartConfig
+ * @param file The file that will be added as the field value
+ * @return The method returns Unit but the new Part is added to the Builder that the extension function is applying on
+ * @see requestBody
+ */
+ protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map, file: File) {
+ val partHeaders = headers.toMutableMap() +
+ ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${file.name}\"")
+ val fileMediaType = guessContentTypeFromFile(file).toMediaTypeOrNull()
+ addPart(
+ partHeaders.toHeaders(),
+ file.asRequestBody(fileMediaType)
+ )
+ }
+
+ /**
+ * Adds any type to a MultipartBody.Builder
+ * Defined a helper in the requestBody method to not duplicate code
+ * It will be used when the content is a FormDataMediaType and the body of the PartConfig is not a File.
+ *
+ * @param name The field name to add in the request
+ * @param headers The headers that are in the PartConfig
+ * @param obj The field name to add in the request
+ * @return The method returns Unit but the new Part is added to the Builder that the extension function is applying on
+ * @see requestBody
+ */
+ protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map, obj: T?) {
+ val partHeaders = headers.toMutableMap() +
+ ("Content-Disposition" to "form-data; name=\"$name\"")
+ addPart(
+ partHeaders.toHeaders(),
+ parameterToString(obj).toRequestBody(null)
+ )
+ }
+
+ protected inline fun requestBody(content: T, mediaType: String?): RequestBody =
+ when {
+ content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull())
+ content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull())
+ mediaType == FormDataMediaType ->
+ MultipartBody.Builder()
+ .setType(MultipartBody.FORM)
+ .apply {
+ // content's type *must* be Map>
+ @Suppress("UNCHECKED_CAST")
+ (content as Map>).forEach { (name, part) ->
+ when (part.body) {
+ is File -> addPartToMultiPart(name, part.headers, part.body)
+ is List<*> -> {
+ part.body.forEach {
+ if (it is File) {
+ addPartToMultiPart(name, part.headers, it)
+ } else {
+ addPartToMultiPart(name, part.headers, it)
+ }
+ }
+ }
+ else -> addPartToMultiPart(name, part.headers, part.body)
+ }
+ }
+ }.build()
+ mediaType == FormUrlEncMediaType -> {
+ FormBody.Builder().apply {
+ // content's type *must* be Map>
+ @Suppress("UNCHECKED_CAST")
+ (content as Map>).forEach { (name, part) ->
+ add(name, parameterToString(part.body))
+ }
+ }.build()
+ }
+ mediaType == null || mediaType.startsWith("application/") && mediaType.endsWith("json") ->
+ if (content == null) {
+ EMPTY_REQUEST
+ } else {
+ Serializer.moshi.adapter(T::class.java).toJson(content)
+ .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull())
+ }
+ mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.")
+ mediaType == TextMediaType && content is String ->
+ content.toRequestBody(TextMediaType.toMediaTypeOrNull())
+ // TODO: this should be extended with other serializers
+ else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, text body, byte body and File body.")
+ }
+
+ @OptIn(ExperimentalStdlibApi::class)
+ protected inline fun responseBody(response: Response, mediaType: String? = JsonMediaType): T? {
+ val body = response.body
+ if(body == null) {
+ return null
+ } else if (T::class.java == Unit::class.java) {
+ // No need to parse the body when we're not interested in the body
+ // Useful when API is returning other Content-Type
+ return null
+ } else if (T::class.java == File::class.java) {
+ // return tempFile
+ val contentDisposition = response.header("Content-Disposition")
+
+ val fileName = if (contentDisposition != null) {
+ // Get filename from the Content-Disposition header.
+ val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?")
+ val matcher = pattern.matcher(contentDisposition)
+ if (matcher.find()) {
+ matcher.group(1)
+ ?.replace(".*[/\\\\]", "")
+ ?.replace(";", "")
+ } else {
+ null
+ }
+ } else {
+ null
+ }
+
+ var prefix: String?
+ val suffix: String?
+ if (fileName == null) {
+ prefix = "download"
+ suffix = ""
+ } else {
+ val pos = fileName.lastIndexOf(".")
+ if (pos == -1) {
+ prefix = fileName
+ suffix = null
+ } else {
+ prefix = fileName.substring(0, pos)
+ suffix = fileName.substring(pos)
+ }
+ // Files.createTempFile requires the prefix to be at least three characters long
+ if (prefix.length < 3) {
+ prefix = "download"
+ }
+ }
+
+ // Attention: if you are developing an android app that supports API Level 25 and below, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options
+ val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile()
+ tempFile.deleteOnExit()
+ body.byteStream().use { inputStream ->
+ tempFile.outputStream().use { tempFileOutputStream ->
+ inputStream.copyTo(tempFileOutputStream)
+ }
+ }
+ return tempFile as T
+ }
+
+ return when {
+ mediaType == null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> {
+ val bodyContent = body.string()
+ if (bodyContent.isEmpty()) {
+ return null
+ }
+ Serializer.moshi.adapter().fromJson(bodyContent)
+ }
+ mediaType == OctetMediaType -> body.bytes() as? T
+ mediaType == TextMediaType -> body.string() as? T
+ else -> throw UnsupportedOperationException("responseBody currently only supports JSON body, text body and byte body.")
+ }
+ }
+
+ protected fun updateAuthParams(requestConfig: RequestConfig) {
+ if (requestConfig.headers[Authorization].isNullOrEmpty()) {
+ accessToken?.let { accessToken ->
+ requestConfig.headers[Authorization] = "Bearer $accessToken"
+ }
+ }
+ }
+
+ protected inline fun request(requestConfig: RequestConfig): ApiResponse {
+ val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.")
+
+ // take authMethod from operation
+ updateAuthParams(requestConfig)
+
+ val url = httpUrl.newBuilder()
+ .addEncodedPathSegments(requestConfig.path.trimStart('/'))
+ .apply {
+ requestConfig.query.forEach { query ->
+ query.value.forEach { queryValue ->
+ addQueryParameter(query.key, queryValue)
+ }
+ }
+ }.build()
+
+ // take content-type/accept from spec or set to default (application/json) if not defined
+ if (requestConfig.body != null && requestConfig.headers[ContentType].isNullOrEmpty()) {
+ requestConfig.headers[ContentType] = JsonMediaType
+ }
+ if (requestConfig.headers[Accept].isNullOrEmpty()) {
+ requestConfig.headers[Accept] = JsonMediaType
+ }
+ val headers = requestConfig.headers
+
+ if (headers[Accept].isNullOrEmpty()) {
+ throw kotlin.IllegalStateException("Missing Accept header. This is required.")
+ }
+
+ val contentType = if (headers[ContentType] != null) {
+ // TODO: support multiple contentType options here.
+ (headers[ContentType] as String).substringBefore(";").lowercase(Locale.US)
+ } else {
+ null
+ }
+
+ val request = when (requestConfig.method) {
+ RequestMethod.DELETE -> Request.Builder().url(url).delete(requestBody(requestConfig.body, contentType))
+ RequestMethod.GET -> Request.Builder().url(url)
+ RequestMethod.HEAD -> Request.Builder().url(url).head()
+ RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(requestConfig.body, contentType))
+ RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(requestConfig.body, contentType))
+ RequestMethod.POST -> Request.Builder().url(url).post(requestBody(requestConfig.body, contentType))
+ RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null)
+ }.apply {
+ val headersBuilder = Headers.Builder()
+ headers.forEach { header ->
+ headersBuilder.add(header.key, header.value)
+ }
+ this.headers(headersBuilder.build())
+ }.build()
+
+ val response = client.newCall(request).execute()
+
+ val accept = response.header(ContentType)?.substringBefore(";")?.lowercase(Locale.US)
+
+ // TODO: handle specific mapping types. e.g. Map>
+ @Suppress("UNNECESSARY_SAFE_CALL")
+ return response.use {
+ when {
+ it.isRedirect -> Redirection(
+ it.code,
+ it.headers.toMultimap()
+ )
+ it.isInformational -> Informational(
+ it.message,
+ it.code,
+ it.headers.toMultimap()
+ )
+ it.isSuccessful -> Success(
+ responseBody(it, accept),
+ it.code,
+ it.headers.toMultimap()
+ )
+ it.isClientError -> ClientError(
+ it.message,
+ it.body?.string(),
+ it.code,
+ it.headers.toMultimap()
+ )
+ else -> ServerError(
+ it.message,
+ it.body?.string(),
+ it.code,
+ it.headers.toMultimap()
+ )
+ }
+ }
+ }
+
+ protected fun parameterToString(value: Any?): String = when (value) {
+ null -> ""
+ is Array<*> -> toMultiValue(value, "csv").toString()
+ is Iterable<*> -> toMultiValue(value, "csv").toString()
+ is OffsetDateTime, is OffsetTime, is LocalDateTime, is LocalDate, is LocalTime ->
+ parseDateToQueryString(value)
+ else -> value.toString()
+ }
+
+ protected inline fun parseDateToQueryString(value : T): String {
+ /*
+ .replace("\"", "") converts the json object string to an actual string for the query parameter.
+ The moshi or gson adapter allows a more generic solution instead of trying to use a native
+ formatter. It also easily allows to provide a simple way to define a custom date format pattern
+ inside a gson/moshi adapter.
+ */
+ return Serializer.moshi.adapter(T::class.java).toJson(value).replace("\"", "")
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt
new file mode 100644
index 00000000000..689fb03cd7a
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt
@@ -0,0 +1,43 @@
+package org.openapitools.client.infrastructure
+
+enum class ResponseType {
+ Success, Informational, Redirection, ClientError, ServerError
+}
+
+interface Response
+
+abstract class ApiResponse(val responseType: ResponseType): Response {
+ abstract val statusCode: Int
+ abstract val headers: Map>
+}
+
+class Success(
+ val data: T,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+): ApiResponse(ResponseType.Success)
+
+class Informational(
+ val statusText: String,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.Informational)
+
+class Redirection(
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.Redirection)
+
+class ClientError(
+ val message: String? = null,
+ val body: Any? = null,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+) : ApiResponse(ResponseType.ClientError)
+
+class ServerError(
+ val message: String? = null,
+ val body: Any? = null,
+ override val statusCode: Int = -1,
+ override val headers: Map> = mapOf()
+): ApiResponse(ResponseType.ServerError)
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt
new file mode 100644
index 00000000000..064b57fc6b8
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt
@@ -0,0 +1,17 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.math.BigDecimal
+
+class BigDecimalAdapter {
+ @ToJson
+ fun toJson(value: BigDecimal): String {
+ return value.toPlainString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigDecimal {
+ return BigDecimal(value)
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt
new file mode 100644
index 00000000000..7df6057b450
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt
@@ -0,0 +1,17 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.math.BigInteger
+
+class BigIntegerAdapter {
+ @ToJson
+ fun toJson(value: BigInteger): String {
+ return value.toString()
+ }
+
+ @FromJson
+ fun fromJson(value: String): BigInteger {
+ return BigInteger(value)
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt
new file mode 100644
index 00000000000..ff5e2a81ee8
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt
@@ -0,0 +1,12 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+
+class ByteArrayAdapter {
+ @ToJson
+ fun toJson(data: ByteArray): String = String(data)
+
+ @FromJson
+ fun fromJson(data: String): ByteArray = data.toByteArray()
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt
new file mode 100644
index 00000000000..c83993b9055
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt
@@ -0,0 +1,18 @@
+@file:Suppress("unused")
+package org.openapitools.client.infrastructure
+
+import java.lang.RuntimeException
+
+open class ClientException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) {
+
+ companion object {
+ private const val serialVersionUID: Long = 123L
+ }
+}
+
+open class ServerException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) {
+
+ companion object {
+ private const val serialVersionUID: Long = 456L
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt
new file mode 100644
index 00000000000..b2e1654479a
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt
@@ -0,0 +1,19 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+
+class LocalDateAdapter {
+ @ToJson
+ fun toJson(value: LocalDate): String {
+ return DateTimeFormatter.ISO_LOCAL_DATE.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): LocalDate {
+ return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE)
+ }
+
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt
new file mode 100644
index 00000000000..e082db94811
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt
@@ -0,0 +1,19 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+
+class LocalDateTimeAdapter {
+ @ToJson
+ fun toJson(value: LocalDateTime): String {
+ return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): LocalDateTime {
+ return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
+ }
+
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt
new file mode 100644
index 00000000000..87437871a31
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt
@@ -0,0 +1,19 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.time.OffsetDateTime
+import java.time.format.DateTimeFormatter
+
+class OffsetDateTimeAdapter {
+ @ToJson
+ fun toJson(value: OffsetDateTime): String {
+ return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)
+ }
+
+ @FromJson
+ fun fromJson(value: String): OffsetDateTime {
+ return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
+ }
+
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt
new file mode 100644
index 00000000000..be00e38fbae
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt
@@ -0,0 +1,11 @@
+package org.openapitools.client.infrastructure
+
+/**
+ * Defines a config object for a given part of a multi-part request.
+ * NOTE: Headers is a Map because rfc2616 defines
+ * multi-valued headers as csv-only.
+ */
+data class PartConfig(
+ val headers: MutableMap = mutableMapOf(),
+ val body: T? = null
+)
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt
new file mode 100644
index 00000000000..6578b9381b7
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt
@@ -0,0 +1,19 @@
+package org.openapitools.client.infrastructure
+
+/**
+ * Defines a config object for a given request.
+ * NOTE: This object doesn't include 'body' because it
+ * allows for caching of the constructed object
+ * for many request definitions.
+ * NOTE: Headers is a Map because rfc2616 defines
+ * multi-valued headers as csv-only.
+ */
+data class RequestConfig(
+ val method: RequestMethod,
+ val path: String,
+ val headers: MutableMap = mutableMapOf(),
+ val params: MutableMap = mutableMapOf(),
+ val query: MutableMap> = mutableMapOf(),
+ val requiresAuthentication: Boolean,
+ val body: T? = null
+)
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt
new file mode 100644
index 00000000000..beb56f07cdd
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt
@@ -0,0 +1,8 @@
+package org.openapitools.client.infrastructure
+
+/**
+ * Provides enumerated HTTP verbs
+ */
+enum class RequestMethod {
+ GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt
new file mode 100644
index 00000000000..9bd2790dc14
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt
@@ -0,0 +1,24 @@
+package org.openapitools.client.infrastructure
+
+import okhttp3.Response
+
+/**
+ * Provides an extension to evaluation whether the response is a 1xx code
+ */
+val Response.isInformational : Boolean get() = this.code in 100..199
+
+/**
+ * Provides an extension to evaluation whether the response is a 3xx code
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+val Response.isRedirect : Boolean get() = this.code in 300..399
+
+/**
+ * Provides an extension to evaluation whether the response is a 4xx code
+ */
+val Response.isClientError : Boolean get() = this.code in 400..499
+
+/**
+ * Provides an extension to evaluation whether the response is a 5xx (Standard) through 999 (non-standard) code
+ */
+val Response.isServerError : Boolean get() = this.code in 500..999
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt
new file mode 100644
index 00000000000..e22592e47d7
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt
@@ -0,0 +1,23 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+
+object Serializer {
+ @JvmStatic
+ val moshiBuilder: Moshi.Builder = Moshi.Builder()
+ .add(OffsetDateTimeAdapter())
+ .add(LocalDateTimeAdapter())
+ .add(LocalDateAdapter())
+ .add(UUIDAdapter())
+ .add(ByteArrayAdapter())
+ .add(URIAdapter())
+ .add(KotlinJsonAdapterFactory())
+ .add(BigDecimalAdapter())
+ .add(BigIntegerAdapter())
+
+ @JvmStatic
+ val moshi: Moshi by lazy {
+ moshiBuilder.build()
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt
new file mode 100644
index 00000000000..979301f7a03
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt
@@ -0,0 +1,13 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.net.URI
+
+class URIAdapter {
+ @ToJson
+ fun toJson(uri: URI): String = uri.toString()
+
+ @FromJson
+ fun fromJson(s: String): URI = URI.create(s)
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt
new file mode 100644
index 00000000000..d050ce08f76
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt
@@ -0,0 +1,13 @@
+package org.openapitools.client.infrastructure
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.ToJson
+import java.util.UUID
+
+class UUIDAdapter {
+ @ToJson
+ fun toJson(uuid: UUID): String = uuid.toString()
+
+ @FromJson
+ fun fromJson(s: String): UUID = UUID.fromString(s)
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/models/FindStuff200Response.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/models/FindStuff200Response.kt
new file mode 100644
index 00000000000..dc0d5c16190
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/main/kotlin/org/openapitools/client/models/FindStuff200Response.kt
@@ -0,0 +1,38 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ *
+ *
+ * @param id
+ */
+
+
+data class FindStuff200Response (
+
+ @Json(name = "id")
+ val id: kotlin.String? = null
+
+) {
+
+
+}
+
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/apis/StuffApiTest.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/apis/StuffApiTest.kt
new file mode 100644
index 00000000000..24be43006b5
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/apis/StuffApiTest.kt
@@ -0,0 +1,37 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.apis
+
+import io.kotlintest.shouldBe
+import io.kotlintest.specs.ShouldSpec
+
+import org.openapitools.client.apis.StuffApi
+import org.openapitools.client.models.FindStuff200Response
+
+class StuffApiTest : ShouldSpec() {
+ init {
+ // uncomment below to create an instance of StuffApi
+ //val apiInstance = StuffApi()
+
+ // to test findStuff
+ should("test findStuff") {
+ // uncomment below to test findStuff
+ //val result : FindStuff200Response = apiInstance.findStuff()
+ //result shouldBe ("TODO")
+ }
+
+ }
+}
diff --git a/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/models/FindStuff200ResponseTest.kt b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/models/FindStuff200ResponseTest.kt
new file mode 100644
index 00000000000..7812f31f990
--- /dev/null
+++ b/samples/client/others/kotlin-jvm-okhttp-path-comments/src/test/kotlin/org/openapitools/client/models/FindStuff200ResponseTest.kt
@@ -0,0 +1,35 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import io.kotlintest.shouldBe
+import io.kotlintest.specs.ShouldSpec
+
+import org.openapitools.client.models.FindStuff200Response
+
+class FindStuff200ResponseTest : ShouldSpec() {
+ init {
+ // uncomment below to create an instance of FindStuff200Response
+ //val modelInstance = FindStuff200Response()
+
+ // to test the property `id`
+ should("test id") {
+ // uncomment below to test the property
+ //modelInstance.id shouldBe ("TODO")
+ }
+
+ }
+}
diff --git a/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/gradlew b/samples/client/petstore/kotlin-jvm-okhttp4-coroutines/gradlew
old mode 100644
new mode 100755