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 + +