diff --git a/bin/openapi3/scala-akka-petstore.sh b/bin/openapi3/scala-akka-petstore.sh
index e7aa8ad499a..736fe031246 100755
--- a/bin/openapi3/scala-akka-petstore.sh
+++ b/bin/openapi3/scala-akka-petstore.sh
@@ -27,6 +27,6 @@ fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
-ags="generate --artifact-id "scala-akka-petstore-client" -t modules/openapi-generator/src/main/resources/scala-akka-client -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g scala-akka -o samples/client/petstore/scala-akka $@"
+ags="generate --artifact-id "scala-akka-petstore-client" -t modules/openapi-generator/src/main/resources/scala-akka-client -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g scala-akka -o samples/openapi3/client/petstore/scala-akka $@"
java $JAVA_OPTS -jar $executable $ags
diff --git a/bin/utils/ensure-up-to-date b/bin/utils/ensure-up-to-date
index 40d84848165..9b1eec0774b 100755
--- a/bin/utils/ensure-up-to-date
+++ b/bin/utils/ensure-up-to-date
@@ -85,6 +85,9 @@ declare -a samples=(
"${root}/bin/cpp-restsdk-petstore.sh"
"${root}/bin/cpp-qt5-qhttpengine-server-petstore.sh"
#"${root}/bin/openapi3/powershell-experimental-petstore.sh"
+"${root}/bin/scala-akka-petstore.sh"
+"${root}/bin/openapi3/scala-akka-petstore.sh"
+"${root}/bin/openapi3/scala-sttp-petstore.sh"
)
# Some special case generators may expect to be run as a stanalone process (e.g. modifying classpath)
diff --git a/samples/openapi3/client/petstore/scala-akka/.openapi-generator-ignore b/samples/openapi3/client/petstore/scala-akka/.openapi-generator-ignore
new file mode 100644
index 00000000000..7484ee590a3
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/.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/openapi3/client/petstore/scala-akka/.openapi-generator/VERSION b/samples/openapi3/client/petstore/scala-akka/.openapi-generator/VERSION
new file mode 100644
index 00000000000..bfbf77eb7fa
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/.openapi-generator/VERSION
@@ -0,0 +1 @@
+4.3.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/scala-akka/README.md b/samples/openapi3/client/petstore/scala-akka/README.md
new file mode 100644
index 00000000000..effa8f548eb
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/README.md
@@ -0,0 +1,121 @@
+# scala-akka-petstore-client
+
+OpenAPI Petstore
+- API version: 1.0.0
+
+This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+
+
+*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)*
+
+## Requirements
+
+Building the API client library requires:
+1. Java 1.7+
+2. Maven/Gradle/SBT
+
+## Installation
+
+To install the API client library to your local Maven repository, simply execute:
+
+```shell
+mvn clean install
+```
+
+To deploy it to a remote Maven repository instead, configure the settings of the repository and execute:
+
+```shell
+mvn clean deploy
+```
+
+Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information.
+
+### Maven users
+
+Add this dependency to your project's POM:
+
+```xml
+
+ org.openapitools
+ scala-akka-petstore-client
+ 1.0.0
+ compile
+
+```
+
+### Gradle users
+
+Add this dependency to your project's build file:
+
+```groovy
+compile "org.openapitools:scala-akka-petstore-client:1.0.0"
+```
+
+### SBT users
+
+```scala
+libraryDependencies += "org.openapitools" % "scala-akka-petstore-client" % "1.0.0"
+```
+
+## Getting Started
+
+## Documentation for API Endpoints
+
+All URIs are relative to *http://petstore.swagger.io/v2*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+*PetApi* | **addPet** | **POST** /pet | Add a new pet to the store
+*PetApi* | **deletePet** | **DELETE** /pet/{petId} | Deletes a pet
+*PetApi* | **findPetsByStatus** | **GET** /pet/findByStatus | Finds Pets by status
+*PetApi* | **findPetsByTags** | **GET** /pet/findByTags | Finds Pets by tags
+*PetApi* | **getPetById** | **GET** /pet/{petId} | Find pet by ID
+*PetApi* | **updatePet** | **PUT** /pet | Update an existing pet
+*PetApi* | **updatePetWithForm** | **POST** /pet/{petId} | Updates a pet in the store with form data
+*PetApi* | **uploadFile** | **POST** /pet/{petId}/uploadImage | uploads an image
+*StoreApi* | **deleteOrder** | **DELETE** /store/order/{orderId} | Delete purchase order by ID
+*StoreApi* | **getInventory** | **GET** /store/inventory | Returns pet inventories by status
+*StoreApi* | **getOrderById** | **GET** /store/order/{orderId} | Find purchase order by ID
+*StoreApi* | **placeOrder** | **POST** /store/order | Place an order for a pet
+*UserApi* | **createUser** | **POST** /user | Create user
+*UserApi* | **createUsersWithArrayInput** | **POST** /user/createWithArray | Creates list of users with given input array
+*UserApi* | **createUsersWithListInput** | **POST** /user/createWithList | Creates list of users with given input array
+*UserApi* | **deleteUser** | **DELETE** /user/{username} | Delete user
+*UserApi* | **getUserByName** | **GET** /user/{username} | Get user by user name
+*UserApi* | **loginUser** | **GET** /user/login | Logs user into the system
+*UserApi* | **logoutUser** | **GET** /user/logout | Logs out current logged in user session
+*UserApi* | **updateUser** | **PUT** /user/{username} | Updated user
+
+
+## Documentation for Models
+
+ - [ApiResponse](ApiResponse.md)
+ - [Category](Category.md)
+ - [InlineObject](InlineObject.md)
+ - [InlineObject1](InlineObject1.md)
+ - [Order](Order.md)
+ - [Pet](Pet.md)
+ - [Tag](Tag.md)
+ - [User](User.md)
+
+
+## Documentation for Authorization
+
+Authentication schemes defined for the API:
+### api_key
+
+- **Type**: API key
+- **API key parameter name**: api_key
+- **Location**: HTTP header
+
+### auth_cookie
+
+- **Type**: API key
+- **API key parameter name**: AUTH_KEY
+- **Location**:
+
+
+## Author
+
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/build.sbt b/samples/openapi3/client/petstore/scala-akka/build.sbt
new file mode 100644
index 00000000000..d19487cbe0d
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/build.sbt
@@ -0,0 +1,27 @@
+version := "1.0.0"
+name := "scala-akka-petstore-client"
+organization := "org.openapitools"
+scalaVersion := "2.12.8"
+
+libraryDependencies ++= Seq(
+ "com.typesafe" % "config" % "1.3.3",
+ "com.typesafe.akka" %% "akka-actor" % "2.5.21",
+ "com.typesafe.akka" %% "akka-stream" % "2.5.21",
+ "com.typesafe.akka" %% "akka-http" % "10.1.7",
+ "org.json4s" %% "json4s-jackson" % "3.6.5",
+ "org.json4s" %% "json4s-ext" % "3.6.5",
+ "de.heikoseeberger" %% "akka-http-json4s" % "1.25.2",
+ // test dependencies
+ "org.scalatest" %% "scalatest" % "3.0.5" % "test",
+ "junit" % "junit" % "4.13" % "test"
+)
+
+resolvers ++= Seq(Resolver.mavenLocal)
+
+scalacOptions := Seq(
+ "-unchecked",
+ "-deprecation",
+ "-feature"
+)
+
+publishArtifact in (Compile, packageDoc) := false
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/scala-akka/pom.xml b/samples/openapi3/client/petstore/scala-akka/pom.xml
new file mode 100644
index 00000000000..bd865860a90
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/pom.xml
@@ -0,0 +1,253 @@
+
+ 4.0.0
+
+ scala-akka-petstore-client
+
+ org.openapitools
+ scala-akka-petstore-client
+ 1.0.0
+
+ jar
+
+
+ UTF-8
+ UTF-8
+
+ 1.8
+ 2.12.8
+ 3.5.3
+ 3.2.11
+ 2.5.21
+ 10.1.7
+ 1.3.3
+ 1.25.2
+ 4.13
+ 3.0.5
+
+ 3.3.1
+
+
+
+
+ org.scala-lang
+ scala-library
+ ${scala.version}
+ provided
+
+
+ com.typesafe
+ config
+ ${typesafeconfig.version}
+
+
+ com.typesafe.akka
+ akka-actor_2.12
+ ${akka.version}
+
+
+ com.typesafe.akka
+ akka-stream_2.12
+ ${akka.version}
+
+
+ com.typesafe.akka
+ akka-http_2.12
+ ${akka.http.version}
+
+
+ org.json4s
+ json4s-jackson_2.12
+ ${json4s.jackson.version}
+
+
+ org.json4s
+ json4s-ext_2.12
+ ${json4s.jackson.version}
+
+
+ de.heikoseeberger
+ akka-http-json4s_2.12
+ ${akka.http.json4s.version}
+
+
+
+
+ org.scalatest
+ scalatest_2.12
+ ${scala.test.version}
+ test
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.2
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.0
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.0.0-M1
+
+
+ enforce-maven
+
+ enforce
+
+
+
+
+ 2.2.0
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.20.1
+
+
+
+ loggerPath
+ conf/log4j.properties
+
+
+ -Xms512m -Xmx1500m
+ methods
+ pertest
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.0.2
+
+
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.6
+
+
+
+ jar
+ test-jar
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.0.0
+
+
+ add_sources
+ generate-sources
+
+ add-source
+
+
+
+
+ src/main/java
+
+
+
+
+
+ add_test_sources
+ generate-test-sources
+
+ add-test-source
+
+
+
+
+ src/test/java
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.7.0
+
+ ${java.version}
+ ${java.version}
+
+
+
+ net.alchim31.maven
+ scala-maven-plugin
+ ${scala.maven.plugin.version}
+
+
+ scala-compile-first
+ process-resources
+
+ add-source
+ compile
+
+
+
+ scala-test-compile
+ process-test-resources
+
+ testCompile
+
+
+
+
+
+ -feature
+
+
+ -Xms128m
+ -Xmx1500m
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/resources/reference.conf b/samples/openapi3/client/petstore/scala-akka/src/main/resources/reference.conf
new file mode 100644
index 00000000000..6d419f988eb
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/resources/reference.conf
@@ -0,0 +1,24 @@
+org.openapitools.client {
+
+ apiRequest {
+
+ compression {
+ enabled: false
+ size-threshold: 0
+ }
+
+ trust-certificates: true
+
+ connection-timeout: 5000ms
+
+ default-headers {
+ "userAgent": "scala-akka-petstore-client_1.0.0"
+ }
+
+ // let you define custom http status code, as in :
+ // { code: 601, reason: "some custom http status code", success: false }
+ custom-codes : []
+ }
+}
+
+spray.can.host-connector.max-redirects = 10
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/EnumsSerializers.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/EnumsSerializers.scala
new file mode 100644
index 00000000000..71ad618e31f
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/EnumsSerializers.scala
@@ -0,0 +1,51 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.api
+
+import org.openapitools.client.model._
+import org.json4s._
+import scala.reflect.ClassTag
+
+object EnumsSerializers {
+
+ def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+
+ new EnumNameSerializer(OrderEnums.Status) :+
+ new EnumNameSerializer(PetEnums.Status)
+
+ private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E)
+ extends Serializer[E#Value] {
+ import JsonDSL._
+
+ val EnumerationClass: Class[E#Value] = classOf[E#Value]
+
+ def deserialize(implicit format: Formats):
+ PartialFunction[(TypeInfo, JValue), E#Value] = {
+ case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) =>
+ json match {
+ case JString(value) =>
+ enum.withName(value)
+ case value =>
+ throw new MappingException(s"Can't convert $value to $EnumerationClass")
+ }
+ }
+
+ private[this] def isValid(json: JValue) = json match {
+ case JString(value) if enum.values.exists(_.toString == value) => true
+ case _ => false
+ }
+
+ def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
+ case i: E#Value => i.toString
+ }
+ }
+
+}
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala
new file mode 100644
index 00000000000..df82ca29fca
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/PetApi.scala
@@ -0,0 +1,163 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.api
+
+import org.openapitools.client.model.ApiResponse
+import java.io.File
+import org.openapitools.client.model.Pet
+import org.openapitools.client.core._
+import org.openapitools.client.core.CollectionFormats._
+import org.openapitools.client.core.ApiKeyLocations._
+
+object PetApi {
+
+ def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new PetApi(baseUrl)
+}
+
+class PetApi(baseUrl: String) {
+
+ /**
+ * Expected answers:
+ * code 200 : Pet (successful operation)
+ * code 405 : (Invalid input)
+ *
+ * @param pet Pet object that needs to be added to the store
+ */
+ def addPet(pet: Pet): ApiRequest[Pet] =
+ ApiRequest[Pet](ApiMethods.POST, baseUrl, "/pet", "application/json")
+ .withBody(pet)
+ .withSuccessResponse[Pet](200)
+ .withErrorResponse[Unit](405)
+
+
+ /**
+ * Expected answers:
+ * code 400 : (Invalid pet value)
+ *
+ * @param petId Pet id to delete
+ * @param apiKey
+ */
+ def deletePet(petId: Long, apiKey: Option[String] = None): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.DELETE, baseUrl, "/pet/{petId}", "application/json")
+ .withPathParam("petId", petId)
+ .withHeaderParam("api_key", apiKey)
+ .withErrorResponse[Unit](400)
+
+
+ /**
+ * Multiple status values can be provided with comma separated strings
+ *
+ * Expected answers:
+ * code 200 : Seq[Pet] (successful operation)
+ * code 400 : (Invalid status value)
+ *
+ * @param status Status values that need to be considered for filter
+ */
+ def findPetsByStatus(status: Seq[String]): ApiRequest[Seq[Pet]] =
+ ApiRequest[Seq[Pet]](ApiMethods.GET, baseUrl, "/pet/findByStatus", "application/json")
+ .withQueryParam("status", ArrayValues(status, CSV))
+ .withSuccessResponse[Seq[Pet]](200)
+ .withErrorResponse[Unit](400)
+
+
+ /**
+ * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
+ *
+ * Expected answers:
+ * code 200 : Seq[Pet] (successful operation)
+ * code 400 : (Invalid tag value)
+ *
+ * @param tags Tags to filter by
+ */
+ def findPetsByTags(tags: Seq[String]): ApiRequest[Seq[Pet]] =
+ ApiRequest[Seq[Pet]](ApiMethods.GET, baseUrl, "/pet/findByTags", "application/json")
+ .withQueryParam("tags", ArrayValues(tags, CSV))
+ .withSuccessResponse[Seq[Pet]](200)
+ .withErrorResponse[Unit](400)
+
+
+ /**
+ * Returns a single pet
+ *
+ * Expected answers:
+ * code 200 : Pet (successful operation)
+ * code 400 : (Invalid ID supplied)
+ * code 404 : (Pet not found)
+ *
+ * Available security schemes:
+ * api_key (apiKey)
+ *
+ * @param petId ID of pet to return
+ */
+ def getPetById(petId: Long)(implicit apiKey: ApiKeyValue): ApiRequest[Pet] =
+ ApiRequest[Pet](ApiMethods.GET, baseUrl, "/pet/{petId}", "application/json")
+ .withApiKey(apiKey, "api_key", HEADER)
+ .withPathParam("petId", petId)
+ .withSuccessResponse[Pet](200)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+ /**
+ * Expected answers:
+ * code 200 : Pet (successful operation)
+ * code 400 : (Invalid ID supplied)
+ * code 404 : (Pet not found)
+ * code 405 : (Validation exception)
+ *
+ * @param pet Pet object that needs to be added to the store
+ */
+ def updatePet(pet: Pet): ApiRequest[Pet] =
+ ApiRequest[Pet](ApiMethods.PUT, baseUrl, "/pet", "application/json")
+ .withBody(pet)
+ .withSuccessResponse[Pet](200)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+ .withErrorResponse[Unit](405)
+
+
+ /**
+ * Expected answers:
+ * code 405 : (Invalid input)
+ *
+ * @param petId ID of pet that needs to be updated
+ * @param name Updated name of the pet
+ * @param status Updated status of the pet
+ */
+ def updatePetWithForm(petId: Long, name: Option[String] = None, status: Option[String] = None): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.POST, baseUrl, "/pet/{petId}", "application/x-www-form-urlencoded")
+ .withFormParam("name", name)
+ .withFormParam("status", status)
+ .withPathParam("petId", petId)
+ .withErrorResponse[Unit](405)
+
+
+ /**
+ * Expected answers:
+ * code 200 : ApiResponse (successful operation)
+ *
+ * @param petId ID of pet to update
+ * @param additionalMetadata Additional data to pass to server
+ * @param file file to upload
+ */
+ def uploadFile(petId: Long, additionalMetadata: Option[String] = None, file: Option[File] = None): ApiRequest[ApiResponse] =
+ ApiRequest[ApiResponse](ApiMethods.POST, baseUrl, "/pet/{petId}/uploadImage", "multipart/form-data")
+ .withFormParam("additionalMetadata", additionalMetadata)
+ .withFormParam("file", file)
+ .withPathParam("petId", petId)
+ .withSuccessResponse[ApiResponse](200)
+
+
+
+
+}
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/StoreApi.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/StoreApi.scala
new file mode 100644
index 00000000000..ba8a34ef6ec
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/StoreApi.scala
@@ -0,0 +1,92 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.api
+
+import org.openapitools.client.model.Order
+import org.openapitools.client.core._
+import org.openapitools.client.core.CollectionFormats._
+import org.openapitools.client.core.ApiKeyLocations._
+
+object StoreApi {
+
+ def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new StoreApi(baseUrl)
+}
+
+class StoreApi(baseUrl: String) {
+
+ /**
+ * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
+ *
+ * Expected answers:
+ * code 400 : (Invalid ID supplied)
+ * code 404 : (Order not found)
+ *
+ * @param orderId ID of the order that needs to be deleted
+ */
+ def deleteOrder(orderId: String): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.DELETE, baseUrl, "/store/order/{orderId}", "application/json")
+ .withPathParam("orderId", orderId)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+ /**
+ * Returns a map of status codes to quantities
+ *
+ * Expected answers:
+ * code 200 : Map[String, Int] (successful operation)
+ *
+ * Available security schemes:
+ * api_key (apiKey)
+ */
+ def getInventory()(implicit apiKey: ApiKeyValue): ApiRequest[Map[String, Int]] =
+ ApiRequest[Map[String, Int]](ApiMethods.GET, baseUrl, "/store/inventory", "application/json")
+ .withApiKey(apiKey, "api_key", HEADER)
+ .withSuccessResponse[Map[String, Int]](200)
+
+
+ /**
+ * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
+ *
+ * Expected answers:
+ * code 200 : Order (successful operation)
+ * code 400 : (Invalid ID supplied)
+ * code 404 : (Order not found)
+ *
+ * @param orderId ID of pet that needs to be fetched
+ */
+ def getOrderById(orderId: Long): ApiRequest[Order] =
+ ApiRequest[Order](ApiMethods.GET, baseUrl, "/store/order/{orderId}", "application/json")
+ .withPathParam("orderId", orderId)
+ .withSuccessResponse[Order](200)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+ /**
+ * Expected answers:
+ * code 200 : Order (successful operation)
+ * code 400 : (Invalid Order)
+ *
+ * @param order order placed for purchasing the pet
+ */
+ def placeOrder(order: Order): ApiRequest[Order] =
+ ApiRequest[Order](ApiMethods.POST, baseUrl, "/store/order", "application/json")
+ .withBody(order)
+ .withSuccessResponse[Order](200)
+ .withErrorResponse[Unit](400)
+
+
+
+
+}
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/UserApi.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/UserApi.scala
new file mode 100644
index 00000000000..54809067608
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/api/UserApi.scala
@@ -0,0 +1,175 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.api
+
+import org.openapitools.client.model.User
+import org.openapitools.client.core._
+import org.openapitools.client.core.CollectionFormats._
+import org.openapitools.client.core.ApiKeyLocations._
+
+object UserApi {
+
+ def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new UserApi(baseUrl)
+}
+
+class UserApi(baseUrl: String) {
+
+ /**
+ * This can only be done by the logged in user.
+ *
+ * Expected answers:
+ * code 0 : (successful operation)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ *
+ * @param user Created user object
+ */
+ def createUser(user: User)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withBody(user)
+ .withDefaultSuccessResponse[Unit]
+
+
+ /**
+ * Expected answers:
+ * code 0 : (successful operation)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ *
+ * @param user List of user object
+ */
+ def createUsersWithArrayInput(user: Seq[User])(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithArray", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withBody(user)
+ .withDefaultSuccessResponse[Unit]
+
+
+ /**
+ * Expected answers:
+ * code 0 : (successful operation)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ *
+ * @param user List of user object
+ */
+ def createUsersWithListInput(user: Seq[User])(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.POST, baseUrl, "/user/createWithList", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withBody(user)
+ .withDefaultSuccessResponse[Unit]
+
+
+ /**
+ * This can only be done by the logged in user.
+ *
+ * Expected answers:
+ * code 400 : (Invalid username supplied)
+ * code 404 : (User not found)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ *
+ * @param username The name that needs to be deleted
+ */
+ def deleteUser(username: String)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.DELETE, baseUrl, "/user/{username}", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withPathParam("username", username)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+ /**
+ * Expected answers:
+ * code 200 : User (successful operation)
+ * code 400 : (Invalid username supplied)
+ * code 404 : (User not found)
+ *
+ * @param username The name that needs to be fetched. Use user1 for testing.
+ */
+ def getUserByName(username: String): ApiRequest[User] =
+ ApiRequest[User](ApiMethods.GET, baseUrl, "/user/{username}", "application/json")
+ .withPathParam("username", username)
+ .withSuccessResponse[User](200)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+ /**
+ * Expected answers:
+ * code 200 : String (successful operation)
+ * Headers :
+ * Set-Cookie - Cookie authentication key for use with the `auth_cookie` apiKey authentication.
+ * X-Rate-Limit - calls per hour allowed by the user
+ * X-Expires-After - date in UTC when toekn expires
+ * code 400 : (Invalid username/password supplied)
+ *
+ * @param username The user name for login
+ * @param password The password for login in clear text
+ */
+ def loginUser(username: String, password: String): ApiRequest[String] =
+ ApiRequest[String](ApiMethods.GET, baseUrl, "/user/login", "application/json")
+ .withQueryParam("username", username)
+ .withQueryParam("password", password)
+ .withSuccessResponse[String](200)
+ .withErrorResponse[Unit](400)
+
+ object LoginUserHeaders {
+ def setCookie(r: ApiReturnWithHeaders) = r.getStringHeader("Set-Cookie")
+ def xRateLimit(r: ApiReturnWithHeaders) = r.getIntHeader("X-Rate-Limit")
+ def xExpiresAfter(r: ApiReturnWithHeaders) = r.getOffsetDateTimeHeader("X-Expires-After")
+ }
+
+ /**
+ * Expected answers:
+ * code 0 : (successful operation)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ */
+ def logoutUser()(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.GET, baseUrl, "/user/logout", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withDefaultSuccessResponse[Unit]
+
+
+ /**
+ * This can only be done by the logged in user.
+ *
+ * Expected answers:
+ * code 400 : (Invalid user supplied)
+ * code 404 : (User not found)
+ *
+ * Available security schemes:
+ * auth_cookie (apiKey)
+ *
+ * @param username name that need to be deleted
+ * @param user Updated user object
+ */
+ def updateUser(username: String, user: User)(implicit apiKey: ApiKeyValue): ApiRequest[Unit] =
+ ApiRequest[Unit](ApiMethods.PUT, baseUrl, "/user/{username}", "application/json")
+ .withApiKey(apiKey, "AUTH_KEY", COOKIE)
+ .withBody(user)
+ .withPathParam("username", username)
+ .withErrorResponse[Unit](400)
+ .withErrorResponse[Unit](404)
+
+
+
+
+}
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiInvoker.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiInvoker.scala
new file mode 100644
index 00000000000..3e6c1dbeb44
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiInvoker.scala
@@ -0,0 +1,291 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.core
+
+import java.io.File
+
+import akka.actor.ActorSystem
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.coding._
+import akka.http.scaladsl.model.Multipart.FormData.BodyPart
+import akka.http.scaladsl.model.Uri.Query
+import akka.http.scaladsl.model._
+import akka.http.scaladsl.model.headers._
+import akka.http.scaladsl.unmarshalling.{ Unmarshal, Unmarshaller }
+import akka.stream.ActorMaterializer
+import akka.stream.scaladsl.Source
+import akka.util.{ ByteString, Timeout }
+import de.heikoseeberger.akkahttpjson4s.Json4sSupport
+import org.json4s._
+import org.json4s.jackson.JsonMethods._
+import org.json4s.jackson.Serialization
+
+import scala.collection.immutable
+import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, Future }
+import scala.reflect.ClassTag
+
+object ApiInvoker {
+
+ def apply()(implicit system: ActorSystem): ApiInvoker =
+ apply(DefaultFormats ++ Serializers.all)
+
+ def apply(serializers: Iterable[Serializer[_]])(implicit system: ActorSystem): ApiInvoker =
+ apply(DefaultFormats ++ Serializers.all ++ serializers)
+
+ def apply(formats: Formats)(implicit system: ActorSystem): ApiInvoker = new ApiInvoker(formats)
+
+
+ /**
+ * Allows request execution without calling apiInvoker.execute(request)
+ * request.response can be used to get a future of the ApiResponse generated.
+ * request.result can be used to get a future of the expected ApiResponse content. If content doesn't match, a
+ * Future will failed with a ClassCastException
+ *
+ * @param request the apiRequest to be executed
+ */
+ implicit class ApiRequestImprovements[T: Manifest](request: ApiRequest[T]) {
+
+ def response(invoker: ApiInvoker)(implicit ec: ExecutionContext, system: ActorSystem): Future[ApiResponse[T]] =
+ response(ec, system, invoker)
+
+ def response(implicit ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[ApiResponse[T]] =
+ invoker.execute(request)
+
+ def result[U <: T](implicit c: ClassTag[U], ec: ExecutionContext, system: ActorSystem, invoker: ApiInvoker): Future[U] =
+ invoker.execute(request).map(_.content).mapTo[U]
+
+ }
+
+ /**
+ * Allows transformation from ApiMethod to spray HttpMethods
+ *
+ * @param method the ApiMethod to be converted
+ */
+ implicit class ApiMethodExtensions(val method: ApiMethod) {
+ def toAkkaHttpMethod: HttpMethod = HttpMethods.getForKey(method.value).getOrElse(HttpMethods.GET)
+ }
+
+}
+
+trait UnitJSONSupport {
+
+}
+
+class ApiInvoker(formats: Formats)(implicit system: ActorSystem) extends CustomContentTypes with Json4sSupport {
+
+ import org.openapitools.client.core.ApiInvoker._
+ import org.openapitools.client.core.ParametersMap._
+
+ implicit val ec: ExecutionContextExecutor = system.dispatcher
+ implicit val jsonFormats: Formats = formats
+
+ protected val settings: ApiSettings = ApiSettings(system)
+
+ private implicit val materializer: ActorMaterializer = ActorMaterializer()
+ private implicit val serialization: Serialization = jackson.Serialization
+
+
+ private val http = Http()
+
+ val CompressionFilter: HttpMessage ⇒ Boolean = (msg: HttpMessage) =>
+ Seq(
+ { _: HttpMessage => settings.compressionEnabled },
+ Encoder.DefaultFilter,
+ (message: HttpMessage) => {
+ val long = message.entity().getContentLengthOption()
+ if (long.isPresent) long.getAsLong > settings.compressionSizeThreshold else true
+ }
+ )
+ .map(f => f(msg))
+ .forall(identity)
+
+
+ private def addAuthentication(credentialsSeq: Seq[Credentials]) = {
+ request: HttpRequest =>
+ credentialsSeq.foldLeft(request) {
+ case (req, BasicCredentials(login, password)) =>
+ req.withHeaders(Authorization(BasicHttpCredentials(login, password)))
+ case (req, ApiKeyCredentials(keyValue, keyName, ApiKeyLocations.HEADER)) =>
+ req.withHeaders(RawHeader(keyName, keyValue.value))
+ case (req, BearerToken(token)) =>
+ req.withHeaders(RawHeader("Authorization", s"Bearer $token"))
+ case (req, _) => req
+ }
+ }
+
+ private def headers(headers: Map[String, Any]): immutable.Seq[HttpHeader] =
+ headers.asFormattedParams
+ .map { case (name, value) => RawHeader(name, value.toString) }
+ .to[immutable.Seq]
+
+
+ private def bodyPart(name: String, value: Any): BodyPart = {
+ value match {
+ case f: File =>
+ BodyPart.fromFile(
+ name,
+ ContentType(MediaTypes.`application/octet-stream`),
+ f,
+ f.length().toInt
+ )
+ case v: String =>
+ BodyPart.Strict(name, v.toString)
+ case NumericValue(v) =>
+ BodyPart.Strict(name, v.toString)
+ case m: ApiModel =>
+ BodyPart.Strict(name, Serialization.write(m))
+ }
+ }
+
+
+ private def formDataContent(request: ApiRequest[_]) = {
+ val params = request.formParams.asFormattedParams
+ if (params.isEmpty)
+ None
+ else
+ Some(
+ normalizedContentType(request.contentType).mediaType match {
+ case MediaTypes.`multipart/form-data` =>
+ Multipart.FormData(Source(params.toList.map { case (name, value) => bodyPart(name, value) }))
+ case MediaTypes.`application/x-www-form-urlencoded` =>
+ FormData(params.mapValues(_.toString))
+ case _: MediaType => // Default : application/x-www-form-urlencoded.
+ FormData(params.mapValues(_.toString))
+ }
+ )
+ }
+
+ private def bodyContent(request: ApiRequest[_]): Option[Any] = request
+ .bodyParam
+ .map(Extraction.decompose)
+ .map(compact)
+
+ private def createRequest(uri: Uri, request: ApiRequest[_]): HttpRequest = {
+ val httpRequest = request.method.toAkkaHttpMethod match {
+ case m@(HttpMethods.GET | HttpMethods.DELETE) => HttpRequest(m, uri)
+ case m@(HttpMethods.POST | HttpMethods.PUT | HttpMethods.PATCH) =>
+ formDataContent(request) orElse bodyContent(request) match {
+ case Some(c: FormData) =>
+ HttpRequest(m, uri, entity = c.toEntity)
+ case Some(c: Multipart.FormData) =>
+ HttpRequest(m, uri, entity = c.toEntity)
+ case Some(c: String) =>
+ HttpRequest(m, uri, entity = HttpEntity(normalizedContentType(request.contentType), ByteString(c)))
+ case _ =>
+ HttpRequest(m, uri, entity = HttpEntity(normalizedContentType(request.contentType), ByteString(" ")))
+ }
+ case m: HttpMethod => HttpRequest(m, uri)
+ }
+
+ addAuthentication(request.credentials)(
+ httpRequest.withHeaders(headers(request.headerParams))
+ )
+ }
+
+ def makeQuery(r: ApiRequest[_]): Query = {
+ r.credentials.foldLeft(r.queryParams) {
+ case (params, ApiKeyCredentials(key, keyName, ApiKeyLocations.QUERY)) =>
+ params + (keyName -> key.value)
+ case (params, _) => params
+ }.asFormattedParams
+ .mapValues(_.toString)
+ .foldRight[Query](Uri.Query.Empty) {
+ case ((name, value), acc) => acc.+:(name, value)
+ }
+ }
+
+ def makeUri(r: ApiRequest[_]): Uri = {
+ val opPath = r.operationPath.replaceAll("\\{format\\}", "json")
+ val opPathWithParams = r.pathParams.asFormattedParams
+ .mapValues(_.toString)
+ .foldLeft(opPath) {
+ case (path, (name, value)) => path.replaceAll(s"\\{$name\\}", value)
+ }
+ val query = makeQuery(r)
+
+ Uri(r.basePath + opPathWithParams).withQuery(query)
+ }
+
+ def execute[T: Manifest](r: ApiRequest[T]): Future[ApiResponse[T]] = {
+ implicit val timeout: Timeout = settings.connectionTimeout
+
+ val request = createRequest(makeUri(r), r)
+
+ http
+ .singleRequest(request)
+ .map { response =>
+ val decoder: Coder with StreamDecoder = response.encoding match {
+ case HttpEncodings.gzip ⇒
+ Gzip
+ case HttpEncodings.deflate ⇒
+ Deflate
+ case HttpEncodings.identity ⇒
+ NoCoding
+ case HttpEncoding(encoding) =>
+ throw new IllegalArgumentException(s"Unsupported encoding: $encoding")
+ }
+
+ decoder.decodeMessage(response)
+ }
+ .flatMap(unmarshallApiResponse(r))
+ }
+
+ def unmarshallApiResponse[T: Manifest](request: ApiRequest[T])(response: HttpResponse): Future[ApiResponse[T]] = {
+ def responseForState[V](state: ResponseState, value: V): ApiResponse[V] = {
+ state match {
+ case ResponseState.Success =>
+ ApiResponse(response.status.intValue, value, response.headers.map(header => (header.name, header.value)).toMap)
+ case ResponseState.Error =>
+ throw ApiError(
+ response.status.intValue,
+ "Error response received",
+ Some(value),
+ headers = response.headers.map(header => (header.name, header.value)).toMap
+ )
+ }
+ }
+ val mf = implicitly(manifest[T])
+ request
+ .responseForCode(response.status.intValue) match {
+ case Some((Manifest.Unit, state: ResponseState)) =>
+ Future(responseForState(state, Unit).asInstanceOf[ApiResponse[T]])
+ case Some((manifest, state: ResponseState)) if manifest == mf =>
+ implicit val m: Unmarshaller[HttpEntity, T] = unmarshaller[T](mf, serialization, formats)
+ Unmarshal(response.entity)
+ .to[T]
+ .recoverWith {
+ case e ⇒ throw ApiError(response.status.intValue, s"Unable to unmarshall content to [$manifest]", Some(response.entity.toString), e)
+ }
+ .map(value => responseForState(state, value))
+ case None | Some(_) =>
+ Future.failed(ApiError(response.status.intValue, "Unexpected response code", Some(response.entity.toString)))
+ }
+ }
+}
+
+sealed trait CustomContentTypes {
+
+ protected def normalizedContentType(original: String): ContentType =
+ ContentType(parseContentType(original).mediaType, () => HttpCharsets.`UTF-8`)
+
+ protected def parseContentType(contentType: String): ContentType = {
+
+ ContentType.parse(contentType) match {
+ case Right(ct: ContentType) =>
+ ct
+ case Left(error: List[ErrorInfo]) =>
+ throw new IllegalArgumentException(
+ s"Error converting '$contentType' to a ContentType header: '${error.map(_.summary).mkString(", ")}'"
+ )
+ }
+ }
+}
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiRequest.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiRequest.scala
new file mode 100644
index 00000000000..3dfa61094de
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiRequest.scala
@@ -0,0 +1,65 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.core
+
+sealed trait ResponseState
+
+object ResponseState {
+
+ case object Success extends ResponseState
+
+ case object Error extends ResponseState
+
+}
+
+case class ApiRequest[U](
+ // required fields
+ method: ApiMethod,
+ basePath: String,
+ operationPath: String,
+ contentType: String,
+
+ // optional fields
+ responses: Map[Int, (Manifest[_], ResponseState)] = Map.empty,
+ bodyParam: Option[Any] = None,
+ formParams: Map[String, Any] = Map.empty,
+ pathParams: Map[String, Any] = Map.empty,
+ queryParams: Map[String, Any] = Map.empty,
+ headerParams: Map[String, Any] = Map.empty,
+ credentials: Seq[Credentials] = List.empty) {
+
+ def withCredentials(cred: Credentials): ApiRequest[U] = copy[U](credentials = credentials :+ cred)
+
+ def withApiKey(key: ApiKeyValue, keyName: String, location: ApiKeyLocation): ApiRequest[U] = withCredentials(ApiKeyCredentials(key, keyName, location))
+
+ def withSuccessResponse[T](code: Int)(implicit m: Manifest[T]): ApiRequest[U] = copy[U](responses = responses + (code -> (m, ResponseState.Success)))
+
+ def withErrorResponse[T](code: Int)(implicit m: Manifest[T]): ApiRequest[U] = copy[U](responses = responses + (code -> (m, ResponseState.Error)))
+
+ def withDefaultSuccessResponse[T](implicit m: Manifest[T]): ApiRequest[U] = withSuccessResponse[T](0)
+
+ def withDefaultErrorResponse[T](implicit m: Manifest[T]): ApiRequest[U] = withErrorResponse[T](0)
+
+ def responseForCode(statusCode: Int): Option[(Manifest[_], ResponseState)] = responses.get(statusCode) orElse responses.get(0)
+
+ def withoutBody(): ApiRequest[U] = copy[U](bodyParam = None)
+
+ def withBody(body: Any): ApiRequest[U] = copy[U](bodyParam = Some(body))
+
+ def withFormParam(name: String, value: Any): ApiRequest[U] = copy[U](formParams = formParams + (name -> value))
+
+ def withPathParam(name: String, value: Any): ApiRequest[U] = copy[U](pathParams = pathParams + (name -> value))
+
+ def withQueryParam(name: String, value: Any): ApiRequest[U] = copy[U](queryParams = queryParams + (name -> value))
+
+ def withHeaderParam(name: String, value: Any): ApiRequest[U] = copy[U](headerParams = headerParams + (name -> value))
+}
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiSettings.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiSettings.scala
new file mode 100644
index 00000000000..2553aeb3c87
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/ApiSettings.scala
@@ -0,0 +1,45 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.core
+
+import java.util.concurrent.TimeUnit
+
+import akka.actor.{ ExtendedActorSystem, Extension, ExtensionKey }
+import akka.http.scaladsl.model.StatusCodes.CustomStatusCode
+import akka.http.scaladsl.model.headers.RawHeader
+import com.typesafe.config.Config
+
+import scala.collection.JavaConverters._
+import scala.concurrent.duration.FiniteDuration
+
+class ApiSettings(config: Config) extends Extension {
+ def this(system: ExtendedActorSystem) = this(system.settings.config)
+
+ private def cfg = config.getConfig("org.openapitools.client.apiRequest")
+
+ val alwaysTrustCertificates: Boolean = cfg.getBoolean("trust-certificates")
+ val defaultHeaders: List[RawHeader] = cfg.getConfig("default-headers").entrySet.asScala.toList.map(c => RawHeader(c.getKey, c.getValue.render))
+ val connectionTimeout = FiniteDuration(cfg.getDuration("connection-timeout", TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS)
+ val compressionEnabled: Boolean = cfg.getBoolean("compression.enabled")
+ val compressionSizeThreshold: Int = cfg.getBytes("compression.size-threshold").toInt
+ val customCodes: List[CustomStatusCode] = cfg.getConfigList("custom-codes").asScala.toList.map { c =>
+ CustomStatusCode(
+ c.getInt("code"))(
+ c.getString("reason"),
+ if (c.hasPath("defaultMessage")) c.getString("defaultMessage") else c.getString("reason"),
+ c.getBoolean("success"),
+ if (c.hasPath("allowsEntity")) c.getBoolean("allowsEntity") else true
+ )
+ }
+}
+
+object ApiSettings extends ExtensionKey[ApiSettings]
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/Serializers.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/Serializers.scala
new file mode 100644
index 00000000000..bb3ac5290ce
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/Serializers.scala
@@ -0,0 +1,29 @@
+package org.openapitools.client.core
+
+import java.time.{LocalDate, LocalDateTime, OffsetDateTime, ZoneId}
+import java.time.format.DateTimeFormatter
+import org.json4s.{Serializer, CustomSerializer, JNull}
+import org.json4s.JsonAST.JString
+
+import scala.util.Try
+
+object Serializers {
+
+ case object DateTimeSerializer extends CustomSerializer[OffsetDateTime]( _ => ( {
+ case JString(s) =>
+ Try(OffsetDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME)) orElse
+ Try(LocalDateTime.parse(s).atZone(ZoneId.systemDefault()).toOffsetDateTime) getOrElse null
+ }, {
+ case d: OffsetDateTime =>
+ JString(d.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
+ }))
+
+ case object LocalDateSerializer extends CustomSerializer[LocalDate]( _ => ( {
+ case JString(s) => LocalDate.parse(s)
+ }, {
+ JString(d.format(DateTimeFormatter.ISO_LOCAL_DATE))
+ }))
+
+ def all: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ DateTimeSerializer :+ LocalDateSerializer
+
+}
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/requests.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/requests.scala
new file mode 100644
index 00000000000..0d3549efec9
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/core/requests.scala
@@ -0,0 +1,197 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.core
+
+import java.io.File
+import java.net.URLEncoder
+
+import scala.util.Try
+
+sealed trait ApiReturnWithHeaders {
+ def headers: Map[String, String]
+
+ def header(name: String): Option[String] = headers.get(name)
+
+ def getStringHeader(name: String): Option[String] = header(name)
+
+ // workaround: return date time header in string instead of datetime object
+ def getDateTimeHeader(name: String): Option[String] = header(name)
+
+ def getIntHeader(name: String): Option[Int] = castedHeader(name, java.lang.Integer.parseInt)
+
+ def getLongHeader(name: String): Option[Long] = castedHeader(name, java.lang.Long.parseLong)
+
+ def getFloatHeader(name: String): Option[Float] = castedHeader(name, java.lang.Float.parseFloat)
+
+ def getDoubleHeader(name: String): Option[Double] = castedHeader(name, java.lang.Double.parseDouble)
+
+ def getBooleanHeader(name: String): Option[Boolean] = castedHeader(name, java.lang.Boolean.parseBoolean)
+
+ private def castedHeader[U](name: String, conversion: String => U): Option[U] = {
+ Try {
+ header(name).map(conversion)
+ }.get
+ }
+}
+
+sealed case class ApiResponse[T](code: Int, content: T, headers: Map[String, String] = Map.empty)
+ extends ApiReturnWithHeaders
+
+sealed case class ApiError[T](code: Int, message: String, responseContent: Option[T], cause: Throwable = null, headers: Map[String, String] = Map.empty)
+ extends Throwable(s"($code) $message.${responseContent.map(s => s" Content : $s").getOrElse("")}", cause)
+ with ApiReturnWithHeaders
+
+sealed case class ApiMethod(value: String)
+
+object ApiMethods {
+ val CONNECT = ApiMethod("CONNECT")
+ val DELETE = ApiMethod("DELETE")
+ val GET = ApiMethod("GET")
+ val HEAD = ApiMethod("HEAD")
+ val OPTIONS = ApiMethod("OPTIONS")
+ val PATCH = ApiMethod("PATCH")
+ val POST = ApiMethod("POST")
+ val PUT = ApiMethod("PUT")
+ val TRACE = ApiMethod("TRACE")
+}
+
+/**
+ * This trait needs to be added to any model defined by the api.
+ */
+trait ApiModel
+
+/**
+ * Single trait defining a credential that can be transformed to a paramName / paramValue tupple
+ */
+sealed trait Credentials {
+ def asQueryParam: Option[(String, String)] = None
+}
+
+sealed case class BasicCredentials(user: String, password: String) extends Credentials
+
+sealed case class BearerToken(token: String) extends Credentials
+
+sealed case class ApiKeyCredentials(key: ApiKeyValue, keyName: String, location: ApiKeyLocation) extends Credentials {
+ override def asQueryParam: Option[(String, String)] = location match {
+ case ApiKeyLocations.QUERY => Some((keyName, key.value))
+ case _ => None
+ }
+}
+
+sealed case class ApiKeyValue(value: String)
+
+sealed trait ApiKeyLocation
+
+object ApiKeyLocations {
+
+ case object QUERY extends ApiKeyLocation
+
+ case object HEADER extends ApiKeyLocation
+
+ case object COOKIE extends ApiKeyLocation
+
+}
+
+
+/**
+ * Case class used to unapply numeric values only in pattern matching
+ *
+ * @param value the string representation of the numeric value
+ */
+sealed case class NumericValue(value: String) {
+ override def toString: String = value
+}
+
+object NumericValue {
+ def unapply(n: Any): Option[NumericValue] = n match {
+ case (_: Int | _: Long | _: Float | _: Double | _: Boolean | _: Byte) => Some(NumericValue(String.valueOf(n)))
+ case _ => None
+ }
+}
+
+/**
+ * Used for params being arrays
+ */
+sealed case class ArrayValues(values: Seq[Any], format: CollectionFormat = CollectionFormats.CSV)
+
+object ArrayValues {
+ def apply(values: Option[Seq[Any]], format: CollectionFormat): ArrayValues =
+ ArrayValues(values.getOrElse(Seq.empty), format)
+
+ def apply(values: Option[Seq[Any]]): ArrayValues = ArrayValues(values, CollectionFormats.CSV)
+}
+
+
+/**
+ * Defines how arrays should be rendered in query strings.
+ */
+sealed trait CollectionFormat
+
+trait MergedArrayFormat extends CollectionFormat {
+ def separator: String
+}
+
+object CollectionFormats {
+
+ case object CSV extends MergedArrayFormat {
+ override val separator = ","
+ }
+
+ case object TSV extends MergedArrayFormat {
+ override val separator = "\t"
+ }
+
+ case object SSV extends MergedArrayFormat {
+ override val separator = " "
+ }
+
+ case object PIPES extends MergedArrayFormat {
+ override val separator = "|"
+ }
+
+ case object MULTI extends CollectionFormat
+
+}
+
+object ParametersMap {
+
+ /**
+ * Pimp parameters maps (Map[String, Any]) in order to transform them in a sequence of String -> Any tupples,
+ * with valid url-encoding, arrays handling, files preservation, ...
+ */
+ implicit class ParametersMapImprovements(val m: Map[String, Any]) {
+
+ def asFormattedParamsList: List[(String, Any)] = m.toList.flatMap(formattedParams)
+
+ def asFormattedParams: Map[String, Any] = m.flatMap(formattedParams)
+
+ private def urlEncode(v: Any) = URLEncoder.encode(String.valueOf(v), "utf-8").replaceAll("\\+", "%20")
+
+ private def formattedParams(tuple: (String, Any)): Seq[(String, Any)] = formattedParams(tuple._1, tuple._2)
+
+ private def formattedParams(name: String, value: Any): Seq[(String, Any)] = value match {
+ case arr: ArrayValues =>
+ arr.format match {
+ case CollectionFormats.MULTI => arr.values.flatMap(formattedParams(name, _))
+ case format: MergedArrayFormat => Seq((name, arr.values.mkString(format.separator)))
+ }
+ case None => Seq.empty
+ case Some(opt) => formattedParams(name, opt)
+ case s: Seq[Any] => formattedParams(name, ArrayValues(s))
+ case v: String => Seq((name, urlEncode(v)))
+ case NumericValue(v) => Seq((name, urlEncode(v)))
+ case f: File => Seq((name, f))
+ case m: ApiModel => Seq((name, m))
+ }
+ }
+
+}
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/ApiResponse.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/ApiResponse.scala
new file mode 100644
index 00000000000..3ddf32c9bda
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/ApiResponse.scala
@@ -0,0 +1,22 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class ApiResponse (
+ code: Option[Int] = None,
+ `type`: Option[String] = None,
+ message: Option[String] = None
+) extends ApiModel
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Category.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Category.scala
new file mode 100644
index 00000000000..e62645a38b2
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Category.scala
@@ -0,0 +1,21 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class Category (
+ id: Option[Long] = None,
+ name: Option[String] = None
+) extends ApiModel
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject.scala
new file mode 100644
index 00000000000..3d9ec200c9f
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject.scala
@@ -0,0 +1,23 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class InlineObject (
+ /* Updated name of the pet */
+ name: Option[String] = None,
+ /* Updated status of the pet */
+ status: Option[String] = None
+) extends ApiModel
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject1.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject1.scala
new file mode 100644
index 00000000000..c41794c43d4
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/InlineObject1.scala
@@ -0,0 +1,24 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import java.io.File
+import org.openapitools.client.core.ApiModel
+
+case class InlineObject1 (
+ /* Additional data to pass to server */
+ additionalMetadata: Option[String] = None,
+ /* file to upload */
+ file: Option[File] = None
+) extends ApiModel
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Order.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Order.scala
new file mode 100644
index 00000000000..95204d35e5d
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Order.scala
@@ -0,0 +1,37 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import java.time.OffsetDateTime
+import org.openapitools.client.core.ApiModel
+
+case class Order (
+ id: Option[Long] = None,
+ petId: Option[Long] = None,
+ quantity: Option[Int] = None,
+ shipDate: Option[OffsetDateTime] = None,
+ /* Order Status */
+ status: Option[OrderEnums.Status] = None,
+ complete: Option[Boolean] = None
+) extends ApiModel
+
+object OrderEnums {
+
+ type Status = Status.Value
+ object Status extends Enumeration {
+ val Placed = Value("placed")
+ val Approved = Value("approved")
+ val Delivered = Value("delivered")
+ }
+
+}
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Pet.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Pet.scala
new file mode 100644
index 00000000000..3a78a7c3f18
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Pet.scala
@@ -0,0 +1,36 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class Pet (
+ id: Option[Long] = None,
+ category: Option[Category] = None,
+ name: String,
+ photoUrls: Seq[String],
+ tags: Option[Seq[Tag]] = None,
+ /* pet status in the store */
+ status: Option[PetEnums.Status] = None
+) extends ApiModel
+
+object PetEnums {
+
+ type Status = Status.Value
+ object Status extends Enumeration {
+ val Available = Value("available")
+ val Pending = Value("pending")
+ val Sold = Value("sold")
+ }
+
+}
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Tag.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Tag.scala
new file mode 100644
index 00000000000..ac0c7763720
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/Tag.scala
@@ -0,0 +1,21 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class Tag (
+ id: Option[Long] = None,
+ name: Option[String] = None
+) extends ApiModel
+
+
diff --git a/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/User.scala b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/User.scala
new file mode 100644
index 00000000000..aad2117b16d
--- /dev/null
+++ b/samples/openapi3/client/petstore/scala-akka/src/main/scala/org/openapitools/client/model/User.scala
@@ -0,0 +1,28 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * The version of the OpenAPI document: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+package org.openapitools.client.model
+
+import org.openapitools.client.core.ApiModel
+
+case class User (
+ id: Option[Long] = None,
+ username: Option[String] = None,
+ firstName: Option[String] = None,
+ lastName: Option[String] = None,
+ email: Option[String] = None,
+ password: Option[String] = None,
+ phone: Option[String] = None,
+ /* User Status */
+ userStatus: Option[Int] = None
+) extends ApiModel
+
+