diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java index c373aaa8c70d..8cee440fc3b7 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java @@ -83,6 +83,7 @@ public void run() { ImmutableList.of( new SupportingFile("pom.mustache", "", "pom.xml"), new SupportingFile("generatorClass.mustache", on(File.separator).join("src/main/java", asPath(targetPackage)), mainClass.concat(".java")), + new SupportingFile("debugGeneratorTest.mustache", on(File.separator).join("src/test/java", asPath("org.openapitools.codegen.debug")), "DebugCodegenLauncher.java"), new SupportingFile("README.mustache", "", "README.md"), new SupportingFile("api.template", "src/main/resources" + File.separator + name,"api.mustache"), new SupportingFile("model.template", "src/main/resources" + File.separator + name,"model.mustache"), diff --git a/modules/openapi-generator/src/main/resources/codegen/README.mustache b/modules/openapi-generator/src/main/resources/codegen/README.mustache index 7b274871839f..c55f0b6ce132 100644 --- a/modules/openapi-generator/src/main/resources/codegen/README.mustache +++ b/modules/openapi-generator/src/main/resources/codegen/README.mustache @@ -64,6 +64,9 @@ The `{{generatorClass}}.java` has comments in it--lots of comments. There is no for reading the code more, though. See how the `{{generatorClass}}` implements `CodegenConfig`. That class has the signature of all values that can be overridden. +You can also step through {{generatorClass}}.java in a debugger. Just debug the JUnit +test in DebugCodegenLauncher. That runs the command line tool and lets you inspect what the code is doing. + For the templates themselves, you have a number of values available to you for generation. You can execute the `java` command from above while passing different debug flags to show the object you have available during client generation: diff --git a/modules/openapi-generator/src/main/resources/codegen/debugGeneratorTest.mustache b/modules/openapi-generator/src/main/resources/codegen/debugGeneratorTest.mustache new file mode 100644 index 000000000000..9a9836c1143b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/codegen/debugGeneratorTest.mustache @@ -0,0 +1,40 @@ +package org.openapitools.codegen.debug; + +import org.junit.Test; +import org.openapitools.codegen.OpenAPIGenerator; + +/*** + * This test allows you to easily launch your code generation software under a debugger. + * Then run this test under debug mode. You will be able to step through your java code + * and then see the results in the out directory. + * + * To experiment with debugging your code generator: + * 1) Set a break point in {{generatorClass}}.java in the postProcessOperationsWithModels() method. + * 2) To launch this test in Eclipse: right-click | Debug As | JUnit Test + * + */ +public class DebugCodegenLauncher +{ + @Test + public void launchCodeGeneratorInDebugMode() + { + // use this test to launch you code generator in the debugger. + // this allows you to easily set break points in {{generatorClass}}. + String commandLineParams = + "generate "+ + "-i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml "+ // sample swagger + "-t ./src/main/resources/{{name}} "+ // template directory + "-o out/{{name}} "+ // output directory + "-g {{name}} "; // use this codegen library + + try{ + OpenAPIGenerator.main( commandLineParams.split(" ") ); + } + catch(Exception ex) { + System.err.println(ex.toString()); + } + catch(Error er) { + System.err.println(er.toString()); + } + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/codegen/generatorClass.mustache b/modules/openapi-generator/src/main/resources/codegen/generatorClass.mustache index cefd218cb506..d7b220b680f5 100644 --- a/modules/openapi-generator/src/main/resources/codegen/generatorClass.mustache +++ b/modules/openapi-generator/src/main/resources/codegen/generatorClass.mustache @@ -32,6 +32,31 @@ public class {{generatorClass}} extends DefaultCodegen implements CodegenConfig return "{{name}}"; } + /** + * Provides an opportunity to inspect and modify operation data before the code is generated. + */ + @SuppressWarnings("unchecked") + @Override + public Map postProcessOperationsWithModels(Map objs, List allModels) { + + // to try debugging your code generator: + // set a break point on the next line. + // then debug the JUnit test called LaunchGeneratorInDebugger + + Map results = super.postProcessOperationsWithModels(objs, allModels); + + Map ops = (Map)results.get("operations"); + ArrayList opList = (ArrayList)ops.get("operation"); + + // iterate over the operation and perhaps modify something + for(CodegenOperation co : opList){ + // example: + // co.httpMethod = co.httpMethod.toLowerCase(); + } + + return results; + } + /** * Returns human-friendly help for the generator. Provide the consumer with help * tips, parameters here diff --git a/modules/openapi-generator/src/main/resources/codegen/pom.mustache b/modules/openapi-generator/src/main/resources/codegen/pom.mustache index cb3712e87ad6..8f9aa292252f 100644 --- a/modules/openapi-generator/src/main/resources/codegen/pom.mustache +++ b/modules/openapi-generator/src/main/resources/codegen/pom.mustache @@ -113,6 +113,16 @@ ${openapi-generator-version} provided + + org.openapitools + openapi-generator-cli + ${openapi-generator-version} + + + junit + junit + ${junit-version} + UTF-8 diff --git a/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/ApiInvoker.scala b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/ApiInvoker.scala new file mode 100644 index 000000000000..38916b55d449 --- /dev/null +++ b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/ApiInvoker.scala @@ -0,0 +1,237 @@ +/** + * Swagger Petstore *_/ ' \" =end -- \\r\\n \\n \\r + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end -- + * + * OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r + * Contact: apiteam@swagger.io *_/ ' \" =end -- \\r\\n \\n \\r + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +package io.swagger.client + +import com.sun.jersey.api.client.Client +import com.sun.jersey.api.client.ClientResponse +import com.sun.jersey.api.client.config.ClientConfig +import com.sun.jersey.api.client.config.DefaultClientConfig +import com.sun.jersey.api.client.filter.LoggingFilter + +import com.sun.jersey.core.util.MultivaluedMapImpl +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart + +import java.io.File +import java.net.URLEncoder +import java.util.UUID +import javax.ws.rs.core.MediaType + +import scala.collection.JavaConverters._ +import scala.collection.mutable + +import com.fasterxml.jackson.module.scala.DefaultScalaModule +import com.fasterxml.jackson.datatype.joda.JodaModule +import com.fasterxml.jackson.core.JsonGenerator.Feature +import com.fasterxml.jackson.databind._ +import com.fasterxml.jackson.annotation._ +import com.fasterxml.jackson.databind.annotation.JsonSerialize + +object ScalaJsonUtil { + def getJsonMapper: ObjectMapper = { + val mapper = new ObjectMapper() + mapper.registerModule(new DefaultScalaModule()) + mapper.registerModule(new JodaModule()) + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT) + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY) + mapper + } +} + +class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, + httpHeaders: mutable.HashMap[String, String] = mutable.HashMap(), + hostMap: mutable.HashMap[String, Client] = mutable.HashMap(), + asyncHttpClient: Boolean = false, + authScheme: String = "", + authPreemptive: Boolean = false +) { + + var defaultHeaders: mutable.HashMap[String, String] = httpHeaders + + def escape(value: String): String = { + URLEncoder.encode(value, "utf-8").replaceAll("\\+", "%20") + } + def escape(values: List[String]): String = { + values.map(escape).mkString(",") + } + + def escape(value: Long): String = value.toString + def escape(value: Double): String = value.toString + def escape(value: Float): String = value.toString + def escape(value: UUID): String = value.toString + + def deserialize(json: String, containerType: String, cls: Class[_]) = { + if (cls == classOf[String]) { + json match { + case s: String => + if (s.startsWith("\"") && s.endsWith("\"") && s.length > 1) { + s.substring(1, s.length - 1) + } else { + s + } + case _ => null + } + } else { + containerType.toLowerCase match { + case "array" => + val typeInfo = mapper.getTypeFactory.constructCollectionType(classOf[java.util.List[_]], cls) + val response = mapper.readValue(json, typeInfo).asInstanceOf[java.util.List[_]] + response.asScala.toList + case "list" => + val typeInfo = mapper.getTypeFactory.constructCollectionType(classOf[java.util.List[_]], cls) + val response = mapper.readValue(json, typeInfo).asInstanceOf[java.util.List[_]] + response.asScala.toList + case _ => + json match { + case e: String if "\"\"" == e => null + case _ => mapper.readValue(json, cls) + } + } + } + } + + def serialize(obj: AnyRef): String = { + if (obj != null) { + obj match { + case e: List[_] => mapper.writeValueAsString(obj.asInstanceOf[List[_]].asJava) + case _ => mapper.writeValueAsString(obj) + } + } else { + null + } + } + + def invokeApi( + host: String, + path: String, + method: String, + queryParams: Map[String, String], + formParams: Map[String, String], + body: AnyRef, + headerParams: Map[String, String], + contentType: String +): String = { + val client = getClient(host) + + val querystring = queryParams.filter(k => k._2 != null).map(k => escape(k._1) + "=" + escape(k._2)).mkString("?", "&", "") + val builder = client.resource(host + path + querystring).accept(contentType) + headerParams.map(p => builder.header(p._1, p._2)) + defaultHeaders.foreach(p => { + if (!headerParams.contains(p._1) && p._2 != null) { + builder.header(p._1, p._2) + } + }) + var formData: MultivaluedMapImpl = null + if (contentType == "application/x-www-form-urlencoded") { + formData = new MultivaluedMapImpl() + formParams.foreach(p => formData.add(p._1, p._2)) + } + + val response: ClientResponse = method match { + case "GET" => builder.get(classOf[ClientResponse]) + case "POST" => + if (formData != null && formData.size() > 0) { + builder.post(classOf[ClientResponse], formData) + } else if (body != null && body.isInstanceOf[File]) { + val file = body.asInstanceOf[File] + val form = new FormDataMultiPart() + form.field("filename", file.getName) + form.bodyPart(new FileDataBodyPart("file", file, MediaType.MULTIPART_FORM_DATA_TYPE)) + builder.post(classOf[ClientResponse], form) + } else { + if (body == null) { + builder.post(classOf[ClientResponse], serialize(body)) + } else { + builder.`type`(contentType).post(classOf[ClientResponse], serialize(body)) + } + } + case "PUT" => + if (formData != null) { + builder.post(classOf[ClientResponse], formData) + } else if (body == null) { + builder.put(classOf[ClientResponse], null) + } else { + builder.`type`(contentType).put(classOf[ClientResponse], serialize(body)) + } + case "DELETE" => builder.delete(classOf[ClientResponse]) + case "PATCH" => + if(formData != null) { + builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], formData) + } else if(body == null) { + builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], null) + } else { + builder.header("X-HTTP-Method-Override", "PATCH").`type`(contentType).post(classOf[ClientResponse], serialize(body)) + } + case _ => null + } + response.getStatusInfo.getStatusCode match { + case 204 => "" + case code: Int if Range(200, 299).contains(code) => + if (response.hasEntity) { + response.getEntity(classOf[String]) + } else { + "" + } + case _ => + val entity = if (response.hasEntity) { + response.getEntity(classOf[String]) + } else { + "no data" + } + throw new ApiException(response.getStatusInfo.getStatusCode, entity) + } + } + + def getClient(host: String): Client = { + if (hostMap.contains(host)) { + hostMap(host) + } else { + val client = newClient(host) + // client.addFilter(new LoggingFilter()) + hostMap += host -> client + client + } + } + + def newClient(host: String): Client = if (asyncHttpClient) { + import com.ning.http.client.Realm + import org.sonatype.spice.jersey.client.ahc.AhcHttpClient + import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig + + val config: DefaultAhcConfig = new DefaultAhcConfig() + if (!authScheme.isEmpty) { + val authSchemeEnum = Realm.AuthScheme.valueOf(authScheme) + config + .getAsyncHttpClientConfigBuilder + .setRealm(new Realm.RealmBuilder().setScheme(authSchemeEnum) + .setUsePreemptiveAuth(authPreemptive).build) + } + AhcHttpClient.create(config) + } else { + Client.create() + } +} + +object ApiInvoker extends ApiInvoker( + mapper = ScalaJsonUtil.getJsonMapper, + httpHeaders = mutable.HashMap(), + hostMap = mutable.HashMap(), + asyncHttpClient = false, + authScheme = "", + authPreemptive = false +) + +class ApiException(val code: Int, msg: String) extends RuntimeException(msg) diff --git a/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/AsyncClient.scala b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/AsyncClient.scala new file mode 100644 index 000000000000..44b642c913c6 --- /dev/null +++ b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/AsyncClient.scala @@ -0,0 +1,20 @@ +package io.swagger.client + +import io.swagger.client.api._ + +import com.wordnik.swagger.client._ + +import java.io.Closeable + +class AsyncClient(config: SwaggerConfig) extends Closeable { + lazy val locator: ServiceLocator = config.locator + lazy val name: String = config.name + + private[this] val client = transportClient + + protected def transportClient: TransportClient = new RestClient(config) + + def close() { + client.close() + } +} diff --git a/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/api/FakeApi.scala b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/api/FakeApi.scala new file mode 100644 index 000000000000..0aaed4e8e81d --- /dev/null +++ b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/api/FakeApi.scala @@ -0,0 +1,118 @@ +/** + * Swagger Petstore *_/ ' \" =end -- \\r\\n \\n \\r + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end -- + * + * OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r + * Contact: apiteam@swagger.io *_/ ' \" =end -- \\r\\n \\n \\r + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +package io.swagger.client.api + +import java.text.SimpleDateFormat + +import io.swagger.client.{ApiInvoker, ApiException} + +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart + +import javax.ws.rs.core.MediaType + +import java.io.File +import java.util.Date + +import scala.collection.mutable.HashMap + +import com.wordnik.swagger.client._ +import scala.concurrent.Future +import collection.mutable + +import java.net.URI + +import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._ +import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._ + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.util.{Failure, Success, Try} + +import org.json4s._ + +class FakeApi( + val defBasePath: String = "https://petstore.swagger.io *_/ ' \" =end -- \\r\\n \\n \\r/v2 *_/ ' \" =end -- \\r\\n \\n \\r", + defApiInvoker: ApiInvoker = ApiInvoker +) { + + implicit val formats = new org.json4s.DefaultFormats { + override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+0000") + } + implicit val stringReader: ClientResponseReader[String] = ClientResponseReaders.StringReader + implicit val unitReader: ClientResponseReader[Unit] = ClientResponseReaders.UnitReader + implicit val jvalueReader: ClientResponseReader[JValue] = ClientResponseReaders.JValueReader + implicit val jsonReader: ClientResponseReader[Nothing] = JsonFormatsReader + implicit val stringWriter: RequestWriter[String] = RequestWriters.StringWriter + implicit val jsonWriter: RequestWriter[Nothing] = JsonFormatsWriter + + var basePath: String = defBasePath + var apiInvoker: ApiInvoker = defApiInvoker + + def addHeader(key: String, value: String): mutable.HashMap[String, String] = { + apiInvoker.defaultHeaders += key -> value + } + + val config: SwaggerConfig = SwaggerConfig.forUrl(new URI(defBasePath)) + val client = new RestClient(config) + val helper = new FakeApiAsyncHelper(client, config) + + /** + * To test code injection *_/ ' \" =end -- \\r\\n \\n \\r + * + * + * @param testCodeInjectEndRnNR To test code injection *_/ ' \" =end -- \\r\\n \\n \\r (optional) + * @return void + */ + def testCodeInject * ' " =end rn n r(testCodeInjectEndRnNR: Option[String] = None) = { + val await = Try(Await.result(testCodeInject * ' " =end rn n rAsync(testCodeInjectEndRnNR), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * To test code injection *_/ ' \" =end -- \\r\\n \\n \\r asynchronously + * + * + * @param testCodeInjectEndRnNR To test code injection *_/ ' \" =end -- \\r\\n \\n \\r (optional) + * @return Future(void) + */ + def testCodeInject * ' " =end rn n rAsync(testCodeInjectEndRnNR: Option[String] = None) = { + helper.testCodeInject * ' " =end rn n r(testCodeInjectEndRnNR) + } + +} + +class FakeApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) { + + def testCodeInject * ' " =end rn n r(testCodeInjectEndRnNR: Option[String] = None + )(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/fake")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("PUT", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + +} diff --git a/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/model/ModelReturn.scala b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/model/ModelReturn.scala new file mode 100644 index 000000000000..61527518a182 --- /dev/null +++ b/samples/client/petstore-security-test/scala-httpclient/bin/io/swagger/client/model/ModelReturn.scala @@ -0,0 +1,20 @@ +/** + * Swagger Petstore *_/ ' \" =end -- \\r\\n \\n \\r + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end -- + * + * OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r + * Contact: apiteam@swagger.io *_/ ' \" =end -- \\r\\n \\n \\r + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +package io.swagger.client.model + + +case class ModelReturn ( + // property description *_/ ' \" =end -- \\r\\n \\n \\r + _return: Option[Integer] = None +) + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/PetApi.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/PetApi.kt new file mode 100644 index 000000000000..72d24c820e7d --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/PetApi.kt @@ -0,0 +1,278 @@ +/** +* 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. +* +* OpenAPI spec version: 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.apis + +import org.openapitools.client.models.ApiResponse +import org.openapitools.client.models.Pet + +import org.openapitools.client.infrastructure.* + +class PetApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) { + + /** + * Add a new pet to the store + * + * @param body Pet object that needs to be added to the store + * @return void + */ + fun addPet(body: Pet) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/pet", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Deletes a pet + * + * @param petId Pet id to delete + * @param apiKey (optional, default to null) + * @return void + */ + fun deletePet(petId: kotlin.Long, apiKey: kotlin.String) : Unit { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf("api_key" to apiKey.toString()) + val localVariableConfig = RequestConfig( + RequestMethod.DELETE, + "/pet/{petId}".replace("{"+"petId"+"}", "$petId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Finds Pets by status + * Multiple status values can be provided with comma separated strings + * @param status Status values that need to be considered for filter + * @return kotlin.Array + */ + @Suppress("UNCHECKED_CAST") + fun findPetsByStatus(status: kotlin.Array) : kotlin.Array { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf("status" to toMultiValue(status.toList(), "csv")) + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/pet/findByStatus", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request>( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as kotlin.Array + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Finds Pets by tags + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * @param tags Tags to filter by + * @return kotlin.Array + */ + @Suppress("UNCHECKED_CAST") + fun findPetsByTags(tags: kotlin.Array) : kotlin.Array { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf("tags" to toMultiValue(tags.toList(), "csv")) + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/pet/findByTags", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request>( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as kotlin.Array + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Find pet by ID + * Returns a single pet + * @param petId ID of pet to return + * @return Pet + */ + @Suppress("UNCHECKED_CAST") + fun getPetById(petId: kotlin.Long) : Pet { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/pet/{petId}".replace("{"+"petId"+"}", "$petId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as Pet + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Update an existing pet + * + * @param body Pet object that needs to be added to the store + * @return void + */ + fun updatePet(body: Pet) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.PUT, + "/pet", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Updates a pet in the store with form data + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet (optional, default to null) + * @param status Updated status of the pet (optional, default to null) + * @return void + */ + fun updatePetWithForm(petId: kotlin.Long, name: kotlin.String, status: kotlin.String) : Unit { + val localVariableBody: kotlin.Any? = mapOf("name" to "$name", "status" to "$status") + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf("Content-Type" to "multipart/form-data") + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/pet/{petId}".replace("{"+"petId"+"}", "$petId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * uploads an image + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server (optional, default to null) + * @param file file to upload (optional, default to null) + * @return ApiResponse + */ + @Suppress("UNCHECKED_CAST") + fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String, file: java.io.File) : ApiResponse { + val localVariableBody: kotlin.Any? = mapOf("additionalMetadata" to "$additionalMetadata", "file" to "$file") + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf("Content-Type" to "multipart/form-data") + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/pet/{petId}/uploadImage".replace("{"+"petId"+"}", "$petId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as ApiResponse + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + +} diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/StoreApi.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/StoreApi.kt new file mode 100644 index 000000000000..bead1dcc3597 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/StoreApi.kt @@ -0,0 +1,146 @@ +/** +* 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. +* +* OpenAPI spec version: 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.apis + +import org.openapitools.client.models.Order + +import org.openapitools.client.infrastructure.* + +class StoreApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) { + + /** + * Delete purchase order by ID + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * @param orderId ID of the order that needs to be deleted + * @return void + */ + fun deleteOrder(orderId: kotlin.String) : Unit { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.DELETE, + "/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Returns pet inventories by status + * Returns a map of status codes to quantities + * @return kotlin.collections.Map + */ + @Suppress("UNCHECKED_CAST") + fun getInventory() : kotlin.collections.Map { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/store/inventory", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request>( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as kotlin.collections.Map + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Find purchase order by ID + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * @param orderId ID of pet that needs to be fetched + * @return Order + */ + @Suppress("UNCHECKED_CAST") + fun getOrderById(orderId: kotlin.Long) : Order { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/store/order/{orderId}".replace("{"+"orderId"+"}", "$orderId"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as Order + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Place an order for a pet + * + * @param body order placed for purchasing the pet + * @return Order + */ + @Suppress("UNCHECKED_CAST") + fun placeOrder(body: Order) : Order { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/store/order", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as Order + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + +} diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/UserApi.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/UserApi.kt new file mode 100644 index 000000000000..130def3847f0 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/apis/UserApi.kt @@ -0,0 +1,271 @@ +/** +* 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. +* +* OpenAPI spec version: 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.apis + +import org.openapitools.client.models.User + +import org.openapitools.client.infrastructure.* + +class UserApi(basePath: kotlin.String = "http://petstore.swagger.io/v2") : ApiClient(basePath) { + + /** + * Create user + * This can only be done by the logged in user. + * @param body Created user object + * @return void + */ + fun createUser(body: User) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/user", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return void + */ + fun createUsersWithArrayInput(body: kotlin.Array) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/user/createWithArray", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Creates list of users with given input array + * + * @param body List of user object + * @return void + */ + fun createUsersWithListInput(body: kotlin.Array) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.POST, + "/user/createWithList", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Delete user + * This can only be done by the logged in user. + * @param username The name that needs to be deleted + * @return void + */ + fun deleteUser(username: kotlin.String) : Unit { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.DELETE, + "/user/{username}".replace("{"+"username"+"}", "$username"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Get user by user name + * + * @param username The name that needs to be fetched. Use user1 for testing. + * @return User + */ + @Suppress("UNCHECKED_CAST") + fun getUserByName(username: kotlin.String) : User { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/user/{username}".replace("{"+"username"+"}", "$username"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as User + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Logs user into the system + * + * @param username The user name for login + * @param password The password for login in clear text + * @return kotlin.String + */ + @Suppress("UNCHECKED_CAST") + fun loginUser(username: kotlin.String, password: kotlin.String) : kotlin.String { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf("username" to listOf("$username"), "password" to listOf("$password")) + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/user/login", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> (response as Success<*>).data as kotlin.String + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Logs out current logged in user session + * + * @return void + */ + fun logoutUser() : Unit { + val localVariableBody: kotlin.Any? = null + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.GET, + "/user/logout", + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + + /** + * Updated user + * This can only be done by the logged in user. + * @param username name that need to be deleted + * @param body Updated user object + * @return void + */ + fun updateUser(username: kotlin.String, body: User) : Unit { + val localVariableBody: kotlin.Any? = body + val localVariableQuery: MultiValueMap = mapOf() + val localVariableHeaders: kotlin.collections.Map = mapOf() + val localVariableConfig = RequestConfig( + RequestMethod.PUT, + "/user/{username}".replace("{"+"username"+"}", "$username"), + query = localVariableQuery, + headers = localVariableHeaders + ) + val response = request( + localVariableConfig, + localVariableBody + ) + + return when (response.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> TODO() + ResponseType.Redirection -> TODO() + ResponseType.ClientError -> throw ClientException((response as ClientError<*>).body as? String ?: "Client error") + ResponseType.ServerError -> throw ServerException((response as ServerError<*>).message ?: "Server error") + else -> throw kotlin.IllegalStateException("Undefined ResponseType.") + } + } + +} diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiAbstractions.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiAbstractions.kt new file mode 100644 index 000000000000..c2c3f1f0eaea --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiAbstractions.kt @@ -0,0 +1,20 @@ +package org.openapitools.client.infrastructure + +typealias MultiValueMap = Map> + +fun collectionDelimiter(collectionFormat: String) = when(collectionFormat) { + "csv" -> "," + "tsv" -> "\t" + "pipes" -> "|" + "ssv" -> " " + else -> "" +} + +val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" } + +fun toMultiValue(items: List, collectionFormat: String, map: (item: Any?) -> String = defaultMultiValueConverter): List { + return when(collectionFormat) { + "multi" -> items.map(map) + else -> listOf(items.map(map).joinToString(separator = collectionDelimiter(collectionFormat))) + } +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiClient.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiClient.kt new file mode 100644 index 000000000000..9e79028a90b1 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiClient.kt @@ -0,0 +1,141 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.Moshi +import com.squareup.moshi.ToJson +import okhttp3.* +import java.io.File +import java.util.* + +open class ApiClient(val baseUrl: String) { + companion object { + protected const val ContentType = "Content-Type" + protected const val Accept = "Accept" + protected const val JsonMediaType = "application/json" + protected const val FormDataMediaType = "multipart/form-data" + protected const val XmlMediaType = "application/xml" + + @JvmStatic + val client by lazy { + builder.build() + } + + @JvmStatic + val builder: OkHttpClient.Builder = OkHttpClient.Builder() + + @JvmStatic + var defaultHeaders: Map by ApplicationDelegates.setOnce(mapOf(ContentType to JsonMediaType, Accept to JsonMediaType)) + + @JvmStatic + val jsonHeaders: Map = mapOf(ContentType to JsonMediaType, Accept to JsonMediaType) + } + + protected inline fun requestBody(content: T, mediaType: String = JsonMediaType): RequestBody = + when { + content is File -> RequestBody.create( + MediaType.parse(mediaType), content + ) + mediaType == FormDataMediaType -> { + var builder = FormBody.Builder() + // content's type *must* be Map + @Suppress("UNCHECKED_CAST") + (content as Map).forEach { key, value -> + builder = builder.add(key, value) + } + builder.build() + } + mediaType == JsonMediaType -> RequestBody.create( + MediaType.parse(mediaType), Serializer.moshi.adapter(T::class.java).toJson(content) + ) + mediaType == XmlMediaType -> TODO("xml not currently supported.") + // TODO: this should be extended with other serializers + else -> TODO("requestBody currently only supports JSON body and File body.") + } + + protected inline fun responseBody(body: ResponseBody?, mediaType: String = JsonMediaType): T? { + if(body == null) return null + return when(mediaType) { + JsonMediaType -> Moshi.Builder().add(object { + @ToJson + fun toJson(uuid: UUID) = uuid.toString() + @FromJson + fun fromJson(s: String) = UUID.fromString(s) + }) + .add(ByteArrayAdapter()) + .build().adapter(T::class.java).fromJson(body.source()) + else -> TODO() + } + } + + protected inline fun request(requestConfig: RequestConfig, body : Any? = null): ApiInfrastructureResponse { + val httpUrl = HttpUrl.parse(baseUrl) ?: throw IllegalStateException("baseUrl is invalid.") + + var urlBuilder = httpUrl.newBuilder() + .addPathSegments(requestConfig.path.trimStart('/')) + + requestConfig.query.forEach { query -> + query.value.forEach { queryValue -> + urlBuilder = urlBuilder.addQueryParameter(query.key, queryValue) + } + } + + val url = urlBuilder.build() + val headers = requestConfig.headers + defaultHeaders + + if(headers[ContentType] ?: "" == "") { + throw kotlin.IllegalStateException("Missing Content-Type header. This is required.") + } + + if(headers[Accept] ?: "" == "") { + throw kotlin.IllegalStateException("Missing Accept header. This is required.") + } + + // TODO: support multiple contentType,accept options here. + val contentType = (headers[ContentType] as String).substringBefore(";").toLowerCase() + val accept = (headers[Accept] as String).substringBefore(";").toLowerCase() + + var request : Request.Builder = when (requestConfig.method) { + RequestMethod.DELETE -> Request.Builder().url(url).delete() + RequestMethod.GET -> Request.Builder().url(url) + RequestMethod.HEAD -> Request.Builder().url(url).head() + RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(body, contentType)) + RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(body, contentType)) + RequestMethod.POST -> Request.Builder().url(url).post(requestBody(body, contentType)) + RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null) + } + + headers.forEach { header -> request = request.addHeader(header.key, header.value) } + + val realRequest = request.build() + val response = client.newCall(realRequest).execute() + + // TODO: handle specific mapping types. e.g. Map> + when { + response.isRedirect -> return Redirection( + response.code(), + response.headers().toMultimap() + ) + response.isInformational -> return Informational( + response.message(), + response.code(), + response.headers().toMultimap() + ) + response.isSuccessful -> return Success( + responseBody(response.body(), accept), + response.code(), + response.headers().toMultimap() + ) + response.isClientError -> return ClientError( + response.body()?.string(), + response.code(), + response.headers().toMultimap() + ) + else -> return ServerError( + null, + response.body()?.string(), + response.code(), + response.headers().toMultimap() + ) + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiInfrastructureResponse.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiInfrastructureResponse.kt new file mode 100644 index 000000000000..f1a8aecc914b --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApiInfrastructureResponse.kt @@ -0,0 +1,40 @@ +package org.openapitools.client.infrastructure + +enum class ResponseType { + Success, Informational, Redirection, ClientError, ServerError +} + +abstract class ApiInfrastructureResponse(val responseType: ResponseType) { + abstract val statusCode: Int + abstract val headers: Map> +} + +class Success( + val data: T, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +): ApiInfrastructureResponse(ResponseType.Success) + +class Informational( + val statusText: String, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiInfrastructureResponse(ResponseType.Informational) + +class Redirection( + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiInfrastructureResponse(ResponseType.Redirection) + +class ClientError( + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiInfrastructureResponse(ResponseType.ClientError) + +class ServerError( + val message: String? = null, + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> +): ApiInfrastructureResponse(ResponseType.ServerError) \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApplicationDelegates.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApplicationDelegates.kt new file mode 100644 index 000000000000..dd34bd48b2c0 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ApplicationDelegates.kt @@ -0,0 +1,29 @@ +package org.openapitools.client.infrastructure + +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +object ApplicationDelegates { + /** + * Provides a property delegate, allowing the property to be set once and only once. + * + * If unset (no default value), a get on the property will throw [IllegalStateException]. + */ + fun setOnce(defaultValue: T? = null) : ReadWriteProperty = SetOnce(defaultValue) + + private class SetOnce(defaultValue: T? = null) : ReadWriteProperty { + private var isSet = false + private var value: T? = defaultValue + + override fun getValue(thisRef: Any?, property: KProperty<*>): T { + return value ?: throw IllegalStateException("${property.name} not initialized") + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = synchronized(this) { + if (!isSet) { + this.value = value + isSet = true + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt new file mode 100644 index 000000000000..617ac3fe9069 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt @@ -0,0 +1,12 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson + +class ByteArrayAdapter { + @ToJson + fun toJson(data: ByteArray): String = String(data) + + @FromJson + fun fromJson(data: String): ByteArray = data.toByteArray() +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Errors.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Errors.kt new file mode 100644 index 000000000000..2f3b0157ba70 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Errors.kt @@ -0,0 +1,42 @@ +@file:Suppress("unused") +package org.openapitools.client.infrastructure + +import java.lang.RuntimeException + +open class ClientException : RuntimeException { + + /** + * Constructs an [ClientException] with no detail message. + */ + constructor() : super() + + /** + * Constructs an [ClientException] with the specified detail message. + + * @param message the detail message. + */ + constructor(message: kotlin.String) : super(message) + + companion object { + private const val serialVersionUID: Long = 123L + } +} + +open class ServerException : RuntimeException { + + /** + * Constructs an [ServerException] with no detail message. + */ + constructor() : super() + + /** + * Constructs an [ServerException] with the specified detail message. + + * @param message the detail message. + */ + constructor(message: kotlin.String) : super(message) + + companion object { + private const val serialVersionUID: Long = 456L + } +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestConfig.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestConfig.kt new file mode 100644 index 000000000000..86e2dadf9a81 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestConfig.kt @@ -0,0 +1,16 @@ +package org.openapitools.client.infrastructure + +/** + * Defines a config object for a given request. + * NOTE: This object doesn't include 'body' because it + * allows for caching of the constructed object + * for many request definitions. + * NOTE: Headers is a Map because rfc2616 defines + * multi-valued headers as csv-only. + */ +data class RequestConfig( + val method: RequestMethod, + val path: String, + val headers: Map = mapOf(), + val query: Map> = mapOf() +) \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestMethod.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestMethod.kt new file mode 100644 index 000000000000..931b12b8bd7a --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/RequestMethod.kt @@ -0,0 +1,8 @@ +package org.openapitools.client.infrastructure + +/** + * Provides enumerated HTTP verbs + */ +enum class RequestMethod { + GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT +} \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ResponseExtensions.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ResponseExtensions.kt new file mode 100644 index 000000000000..f50104a6f352 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/ResponseExtensions.kt @@ -0,0 +1,23 @@ +package org.openapitools.client.infrastructure + +import okhttp3.Response + +/** + * Provides an extension to evaluation whether the response is a 1xx code + */ +val Response.isInformational : Boolean get() = this.code() in 100..199 + +/** + * Provides an extension to evaluation whether the response is a 3xx code + */ +val Response.isRedirect : Boolean get() = this.code() in 300..399 + +/** + * Provides an extension to evaluation whether the response is a 4xx code + */ +val Response.isClientError : Boolean get() = this.code() in 400..499 + +/** + * Provides an extension to evaluation whether the response is a 5xx (Standard) through 999 (non-standard) code + */ +val Response.isServerError : Boolean get() = this.code() in 500..999 \ No newline at end of file diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Serializer.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Serializer.kt new file mode 100644 index 000000000000..cf3fe8203d5b --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/infrastructure/Serializer.kt @@ -0,0 +1,14 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.KotlinJsonAdapterFactory +import com.squareup.moshi.Moshi +import com.squareup.moshi.Rfc3339DateJsonAdapter +import java.util.* + +object Serializer { + @JvmStatic + val moshi: Moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .add(Date::class.java, Rfc3339DateJsonAdapter().nullSafe()) + .build() +} diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/ApiResponse.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/ApiResponse.kt new file mode 100644 index 000000000000..b950bdafb571 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/ApiResponse.kt @@ -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. +* +* OpenAPI spec version: 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.models + + +/** + * Describes the result of uploading an image resource + * @param code + * @param type + * @param message + */ +data class ApiResponse ( + val code: kotlin.Int? = null, + val type: kotlin.String? = null, + val message: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Category.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Category.kt new file mode 100644 index 000000000000..af700f5488a3 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Category.kt @@ -0,0 +1,26 @@ +/** +* 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. +* +* OpenAPI spec version: 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.models + + +/** + * A category for a pet + * @param id + * @param name + */ +data class Category ( + val id: kotlin.Long? = null, + val name: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Order.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Order.kt new file mode 100644 index 000000000000..44a8b1f896c4 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Order.kt @@ -0,0 +1,50 @@ +/** +* 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. +* +* OpenAPI spec version: 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.models + + +import com.squareup.moshi.Json +/** + * An order for a pets from the pet store + * @param id + * @param petId + * @param quantity + * @param shipDate + * @param status Order Status + * @param complete + */ +data class Order ( + val id: kotlin.Long? = null, + val petId: kotlin.Long? = null, + val quantity: kotlin.Int? = null, + val shipDate: java.time.LocalDateTime? = null, + /* Order Status */ + val status: Order.Status? = null, + val complete: kotlin.Boolean? = null +) { + + /** + * Order Status + * Values: placed,approved,delivered + */ + enum class Status(val value: kotlin.String){ + + @Json(name = "placed") placed("placed"), + + @Json(name = "approved") approved("approved"), + + @Json(name = "delivered") delivered("delivered"); + + } + +} + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Pet.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Pet.kt new file mode 100644 index 000000000000..583dd3fb3ae9 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Pet.kt @@ -0,0 +1,52 @@ +/** +* 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. +* +* OpenAPI spec version: 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.models + +import org.openapitools.client.models.Category +import org.openapitools.client.models.Tag + +import com.squareup.moshi.Json +/** + * A pet for sale in the pet store + * @param id + * @param category + * @param name + * @param photoUrls + * @param tags + * @param status pet status in the store + */ +data class Pet ( + val name: kotlin.String, + val photoUrls: kotlin.Array, + val id: kotlin.Long? = null, + val category: Category? = null, + val tags: kotlin.Array? = null, + /* pet status in the store */ + val status: Pet.Status? = null +) { + + /** + * pet status in the store + * Values: available,pending,sold + */ + enum class Status(val value: kotlin.String){ + + @Json(name = "available") available("available"), + + @Json(name = "pending") pending("pending"), + + @Json(name = "sold") sold("sold"); + + } + +} + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Tag.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Tag.kt new file mode 100644 index 000000000000..d2ae2ead613f --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/Tag.kt @@ -0,0 +1,26 @@ +/** +* 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. +* +* OpenAPI spec version: 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.models + + +/** + * A tag for a pet + * @param id + * @param name + */ +data class Tag ( + val id: kotlin.Long? = null, + val name: kotlin.String? = null +) { + +} + diff --git a/samples/client/petstore/kotlin/bin/org/openapitools/client/models/User.kt b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/User.kt new file mode 100644 index 000000000000..a9695bb62ba7 --- /dev/null +++ b/samples/client/petstore/kotlin/bin/org/openapitools/client/models/User.kt @@ -0,0 +1,39 @@ +/** +* 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. +* +* OpenAPI spec version: 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.models + + +/** + * A User who is purchasing from the pet store + * @param id + * @param username + * @param firstName + * @param lastName + * @param email + * @param password + * @param phone + * @param userStatus User Status + */ +data class User ( + val id: kotlin.Long? = null, + val username: kotlin.String? = null, + val firstName: kotlin.String? = null, + val lastName: kotlin.String? = null, + val email: kotlin.String? = null, + val password: kotlin.String? = null, + val phone: kotlin.String? = null, + /* User Status */ + val userStatus: kotlin.Int? = null +) { + +} + diff --git a/samples/client/petstore/scala-gatling/bin/gatling/CD.conf b/samples/client/petstore/scala-gatling/bin/gatling/CD.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/CD.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/CI.conf b/samples/client/petstore/scala-gatling/bin/gatling/CI.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/CI.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/addPet-BodyParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/addPet-BodyParams.csv new file mode 100644 index 000000000000..9c23144ca977 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/addPet-BodyParams.csv @@ -0,0 +1 @@ +photoUrls,name,id,category,tags,status \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/baseline.conf b/samples/client/petstore/scala-gatling/bin/gatling/baseline.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/baseline.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/createUser-BodyParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/createUser-BodyParams.csv new file mode 100644 index 000000000000..38dcc63f0202 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/createUser-BodyParams.csv @@ -0,0 +1 @@ +firstName,lastName,password,userStatus,phone,id,email,username \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/default.conf b/samples/client/petstore/scala-gatling/bin/gatling/default.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/default.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/deleteOrder-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/deleteOrder-pathParams.csv new file mode 100644 index 000000000000..1b404007da94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/deleteOrder-pathParams.csv @@ -0,0 +1 @@ +orderId \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/deletePet-headerParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/deletePet-headerParams.csv new file mode 100644 index 000000000000..afbd34a4d636 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/deletePet-headerParams.csv @@ -0,0 +1 @@ +api_key \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/deletePet-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/deletePet-pathParams.csv new file mode 100644 index 000000000000..45e87671b9aa --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/deletePet-pathParams.csv @@ -0,0 +1 @@ +petId \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/deleteUser-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/deleteUser-pathParams.csv new file mode 100644 index 000000000000..22947b68d01c --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/deleteUser-pathParams.csv @@ -0,0 +1 @@ +username \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/findPetsByStatus-queryParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/findPetsByStatus-queryParams.csv new file mode 100644 index 000000000000..962a7f7e76ee --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/findPetsByStatus-queryParams.csv @@ -0,0 +1 @@ +status \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/findPetsByTags-queryParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/findPetsByTags-queryParams.csv new file mode 100644 index 000000000000..55cf73544d2f --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/findPetsByTags-queryParams.csv @@ -0,0 +1 @@ +tags \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/getOrderById-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/getOrderById-pathParams.csv new file mode 100644 index 000000000000..1b404007da94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/getOrderById-pathParams.csv @@ -0,0 +1 @@ +orderId \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/getPetById-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/getPetById-pathParams.csv new file mode 100644 index 000000000000..45e87671b9aa --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/getPetById-pathParams.csv @@ -0,0 +1 @@ +petId \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/getUserByName-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/getUserByName-pathParams.csv new file mode 100644 index 000000000000..22947b68d01c --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/getUserByName-pathParams.csv @@ -0,0 +1 @@ +username \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/logback.xml b/samples/client/petstore/scala-gatling/bin/gatling/logback.xml new file mode 100644 index 000000000000..f60d0182ac31 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/logback.xml @@ -0,0 +1,22 @@ + + + + + + %d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx + + false + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/loginUser-queryParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/loginUser-queryParams.csv new file mode 100644 index 000000000000..d8bc9aec67d0 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/loginUser-queryParams.csv @@ -0,0 +1 @@ +username,password \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/longevity.conf b/samples/client/petstore/scala-gatling/bin/gatling/longevity.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/longevity.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/PetApiSimulation.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/PetApiSimulation.scala new file mode 100644 index 000000000000..805e05dfc603 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/PetApiSimulation.scala @@ -0,0 +1,209 @@ +package org.openapitools.client.api + +import org.openapitools.client.model._ +import com.typesafe.config.ConfigFactory + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.core.structure.PopulationBuilder + +import java.io.File + +import scala.collection.mutable + +class PetApiSimulation extends Simulation { + + def getCurrentDirectory = new File("").getAbsolutePath + def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data" + + // basic test setup + val configName = System.getProperty("testConfig", "baseline") + val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default")) + val durationSeconds = config.getInt("performance.durationSeconds") + val rampUpSeconds = config.getInt("performance.rampUpSeconds") + val rampDownSeconds = config.getInt("performance.rampDownSeconds") + val authentication = config.getString("performance.authorizationHeader") + val acceptHeader = config.getString("performance.acceptType") + val contentTypeHeader = config.getString("performance.contentType") + val rateMultiplier = config.getDouble("performance.rateMultiplier") + val instanceMultiplier = config.getDouble("performance.instanceMultiplier") + + // global assertion data + val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte") + val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte") + val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte") + val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte") + val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte") + val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte") + val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte") + val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte") + val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte") + val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte") + +// Setup http protocol configuration + val httpConf = http + .baseURL("http://petstore.swagger.io/v2") + .doNotTrackHeader("1") + .acceptLanguageHeader("en-US,en;q=0.5") + .acceptEncodingHeader("gzip, deflate") + .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") + .acceptHeader(acceptHeader) + .contentTypeHeader(contentTypeHeader) + + // set authorization header if it has been modified from config + if(!authentication.equals("~MANUAL_ENTRY")){ + httpConf.authorizationHeader(authentication) + } + + // Setup all the operations per second for the test to ultimately be generated from configs + val addPetPerSecond = config.getDouble("performance.operationsPerSecond.addPet") * rateMultiplier * instanceMultiplier + val deletePetPerSecond = config.getDouble("performance.operationsPerSecond.deletePet") * rateMultiplier * instanceMultiplier + val findPetsByStatusPerSecond = config.getDouble("performance.operationsPerSecond.findPetsByStatus") * rateMultiplier * instanceMultiplier + val findPetsByTagsPerSecond = config.getDouble("performance.operationsPerSecond.findPetsByTags") * rateMultiplier * instanceMultiplier + val getPetByIdPerSecond = config.getDouble("performance.operationsPerSecond.getPetById") * rateMultiplier * instanceMultiplier + val updatePetPerSecond = config.getDouble("performance.operationsPerSecond.updatePet") * rateMultiplier * instanceMultiplier + val updatePetWithFormPerSecond = config.getDouble("performance.operationsPerSecond.updatePetWithForm") * rateMultiplier * instanceMultiplier + val uploadFilePerSecond = config.getDouble("performance.operationsPerSecond.uploadFile") * rateMultiplier * instanceMultiplier + + val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]() + + // Set up CSV feeders + val deletePetHEADERFeeder = csv(userDataDirectory + File.separator + "deletePet-headerParams.csv").random + val deletePetPATHFeeder = csv(userDataDirectory + File.separator + "deletePet-pathParams.csv").random + val findPetsByStatusQUERYFeeder = csv(userDataDirectory + File.separator + "findPetsByStatus-queryParams.csv").random + val findPetsByTagsQUERYFeeder = csv(userDataDirectory + File.separator + "findPetsByTags-queryParams.csv").random + val getPetByIdPATHFeeder = csv(userDataDirectory + File.separator + "getPetById-pathParams.csv").random + val updatePetWithFormPATHFeeder = csv(userDataDirectory + File.separator + "updatePetWithForm-pathParams.csv").random + val uploadFilePATHFeeder = csv(userDataDirectory + File.separator + "uploadFile-pathParams.csv").random + + // Setup all scenarios + + + val scnaddPet = scenario("addPetSimulation") + .exec(http("addPet") + .httpRequest("POST","/pet") +) + + // Run scnaddPet with warm up and reach a constant rate for entire duration + scenarioBuilders += scnaddPet.inject( + rampUsersPerSec(1) to(addPetPerSecond) during(rampUpSeconds), + constantUsersPerSec(addPetPerSecond) during(durationSeconds), + rampUsersPerSec(addPetPerSecond) to(1) during(rampDownSeconds) + ) + + + val scndeletePet = scenario("deletePetSimulation") + .feed(deletePetHEADERFeeder) + .feed(deletePetPATHFeeder) + .exec(http("deletePet") + .httpRequest("DELETE","/pet/${petId}") + .header("api_key","${api_key}") +) + + // Run scndeletePet with warm up and reach a constant rate for entire duration + scenarioBuilders += scndeletePet.inject( + rampUsersPerSec(1) to(deletePetPerSecond) during(rampUpSeconds), + constantUsersPerSec(deletePetPerSecond) during(durationSeconds), + rampUsersPerSec(deletePetPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnfindPetsByStatus = scenario("findPetsByStatusSimulation") + .feed(findPetsByStatusQUERYFeeder) + .exec(http("findPetsByStatus") + .httpRequest("GET","/pet/findByStatus") + .queryParam("status","${status}") +) + + // Run scnfindPetsByStatus with warm up and reach a constant rate for entire duration + scenarioBuilders += scnfindPetsByStatus.inject( + rampUsersPerSec(1) to(findPetsByStatusPerSecond) during(rampUpSeconds), + constantUsersPerSec(findPetsByStatusPerSecond) during(durationSeconds), + rampUsersPerSec(findPetsByStatusPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnfindPetsByTags = scenario("findPetsByTagsSimulation") + .feed(findPetsByTagsQUERYFeeder) + .exec(http("findPetsByTags") + .httpRequest("GET","/pet/findByTags") + .queryParam("tags","${tags}") +) + + // Run scnfindPetsByTags with warm up and reach a constant rate for entire duration + scenarioBuilders += scnfindPetsByTags.inject( + rampUsersPerSec(1) to(findPetsByTagsPerSecond) during(rampUpSeconds), + constantUsersPerSec(findPetsByTagsPerSecond) during(durationSeconds), + rampUsersPerSec(findPetsByTagsPerSecond) to(1) during(rampDownSeconds) + ) + + + val scngetPetById = scenario("getPetByIdSimulation") + .feed(getPetByIdPATHFeeder) + .exec(http("getPetById") + .httpRequest("GET","/pet/${petId}") +) + + // Run scngetPetById with warm up and reach a constant rate for entire duration + scenarioBuilders += scngetPetById.inject( + rampUsersPerSec(1) to(getPetByIdPerSecond) during(rampUpSeconds), + constantUsersPerSec(getPetByIdPerSecond) during(durationSeconds), + rampUsersPerSec(getPetByIdPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnupdatePet = scenario("updatePetSimulation") + .exec(http("updatePet") + .httpRequest("PUT","/pet") +) + + // Run scnupdatePet with warm up and reach a constant rate for entire duration + scenarioBuilders += scnupdatePet.inject( + rampUsersPerSec(1) to(updatePetPerSecond) during(rampUpSeconds), + constantUsersPerSec(updatePetPerSecond) during(durationSeconds), + rampUsersPerSec(updatePetPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnupdatePetWithForm = scenario("updatePetWithFormSimulation") + .feed(updatePetWithFormPATHFeeder) + .exec(http("updatePetWithForm") + .httpRequest("POST","/pet/${petId}") +) + + // Run scnupdatePetWithForm with warm up and reach a constant rate for entire duration + scenarioBuilders += scnupdatePetWithForm.inject( + rampUsersPerSec(1) to(updatePetWithFormPerSecond) during(rampUpSeconds), + constantUsersPerSec(updatePetWithFormPerSecond) during(durationSeconds), + rampUsersPerSec(updatePetWithFormPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnuploadFile = scenario("uploadFileSimulation") + .feed(uploadFilePATHFeeder) + .exec(http("uploadFile") + .httpRequest("POST","/pet/${petId}/uploadImage") +) + + // Run scnuploadFile with warm up and reach a constant rate for entire duration + scenarioBuilders += scnuploadFile.inject( + rampUsersPerSec(1) to(uploadFilePerSecond) during(rampUpSeconds), + constantUsersPerSec(uploadFilePerSecond) during(durationSeconds), + rampUsersPerSec(uploadFilePerSecond) to(1) during(rampDownSeconds) + ) + + setUp( + scenarioBuilders.toList + ).protocols(httpConf).assertions( + global.responseTime.min.lte(globalResponseTimeMinLTE), + global.responseTime.min.gte(globalResponseTimeMinGTE), + global.responseTime.max.lte(globalResponseTimeMaxLTE), + global.responseTime.max.gte(globalResponseTimeMaxGTE), + global.responseTime.mean.lte(globalResponseTimeMeanLTE), + global.responseTime.mean.gte(globalResponseTimeMeanGTE), + global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE), + global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE), + global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE), + global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE) + ) +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/StoreApiSimulation.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/StoreApiSimulation.scala new file mode 100644 index 000000000000..3bf491c31a3a --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/StoreApiSimulation.scala @@ -0,0 +1,140 @@ +package org.openapitools.client.api + +import org.openapitools.client.model._ +import com.typesafe.config.ConfigFactory + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.core.structure.PopulationBuilder + +import java.io.File + +import scala.collection.mutable + +class StoreApiSimulation extends Simulation { + + def getCurrentDirectory = new File("").getAbsolutePath + def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data" + + // basic test setup + val configName = System.getProperty("testConfig", "baseline") + val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default")) + val durationSeconds = config.getInt("performance.durationSeconds") + val rampUpSeconds = config.getInt("performance.rampUpSeconds") + val rampDownSeconds = config.getInt("performance.rampDownSeconds") + val authentication = config.getString("performance.authorizationHeader") + val acceptHeader = config.getString("performance.acceptType") + val contentTypeHeader = config.getString("performance.contentType") + val rateMultiplier = config.getDouble("performance.rateMultiplier") + val instanceMultiplier = config.getDouble("performance.instanceMultiplier") + + // global assertion data + val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte") + val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte") + val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte") + val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte") + val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte") + val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte") + val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte") + val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte") + val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte") + val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte") + +// Setup http protocol configuration + val httpConf = http + .baseURL("http://petstore.swagger.io/v2") + .doNotTrackHeader("1") + .acceptLanguageHeader("en-US,en;q=0.5") + .acceptEncodingHeader("gzip, deflate") + .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") + .acceptHeader(acceptHeader) + .contentTypeHeader(contentTypeHeader) + + // set authorization header if it has been modified from config + if(!authentication.equals("~MANUAL_ENTRY")){ + httpConf.authorizationHeader(authentication) + } + + // Setup all the operations per second for the test to ultimately be generated from configs + val deleteOrderPerSecond = config.getDouble("performance.operationsPerSecond.deleteOrder") * rateMultiplier * instanceMultiplier + val getInventoryPerSecond = config.getDouble("performance.operationsPerSecond.getInventory") * rateMultiplier * instanceMultiplier + val getOrderByIdPerSecond = config.getDouble("performance.operationsPerSecond.getOrderById") * rateMultiplier * instanceMultiplier + val placeOrderPerSecond = config.getDouble("performance.operationsPerSecond.placeOrder") * rateMultiplier * instanceMultiplier + + val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]() + + // Set up CSV feeders + val deleteOrderPATHFeeder = csv(userDataDirectory + File.separator + "deleteOrder-pathParams.csv").random + val getOrderByIdPATHFeeder = csv(userDataDirectory + File.separator + "getOrderById-pathParams.csv").random + + // Setup all scenarios + + + val scndeleteOrder = scenario("deleteOrderSimulation") + .feed(deleteOrderPATHFeeder) + .exec(http("deleteOrder") + .httpRequest("DELETE","/store/order/${orderId}") +) + + // Run scndeleteOrder with warm up and reach a constant rate for entire duration + scenarioBuilders += scndeleteOrder.inject( + rampUsersPerSec(1) to(deleteOrderPerSecond) during(rampUpSeconds), + constantUsersPerSec(deleteOrderPerSecond) during(durationSeconds), + rampUsersPerSec(deleteOrderPerSecond) to(1) during(rampDownSeconds) + ) + + + val scngetInventory = scenario("getInventorySimulation") + .exec(http("getInventory") + .httpRequest("GET","/store/inventory") +) + + // Run scngetInventory with warm up and reach a constant rate for entire duration + scenarioBuilders += scngetInventory.inject( + rampUsersPerSec(1) to(getInventoryPerSecond) during(rampUpSeconds), + constantUsersPerSec(getInventoryPerSecond) during(durationSeconds), + rampUsersPerSec(getInventoryPerSecond) to(1) during(rampDownSeconds) + ) + + + val scngetOrderById = scenario("getOrderByIdSimulation") + .feed(getOrderByIdPATHFeeder) + .exec(http("getOrderById") + .httpRequest("GET","/store/order/${orderId}") +) + + // Run scngetOrderById with warm up and reach a constant rate for entire duration + scenarioBuilders += scngetOrderById.inject( + rampUsersPerSec(1) to(getOrderByIdPerSecond) during(rampUpSeconds), + constantUsersPerSec(getOrderByIdPerSecond) during(durationSeconds), + rampUsersPerSec(getOrderByIdPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnplaceOrder = scenario("placeOrderSimulation") + .exec(http("placeOrder") + .httpRequest("POST","/store/order") +) + + // Run scnplaceOrder with warm up and reach a constant rate for entire duration + scenarioBuilders += scnplaceOrder.inject( + rampUsersPerSec(1) to(placeOrderPerSecond) during(rampUpSeconds), + constantUsersPerSec(placeOrderPerSecond) during(durationSeconds), + rampUsersPerSec(placeOrderPerSecond) to(1) during(rampDownSeconds) + ) + + setUp( + scenarioBuilders.toList + ).protocols(httpConf).assertions( + global.responseTime.min.lte(globalResponseTimeMinLTE), + global.responseTime.min.gte(globalResponseTimeMinGTE), + global.responseTime.max.lte(globalResponseTimeMaxLTE), + global.responseTime.max.gte(globalResponseTimeMaxGTE), + global.responseTime.mean.lte(globalResponseTimeMeanLTE), + global.responseTime.mean.gte(globalResponseTimeMeanGTE), + global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE), + global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE), + global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE), + global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE) + ) +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/UserApiSimulation.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/UserApiSimulation.scala new file mode 100644 index 000000000000..c12112e8b0da --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/api/UserApiSimulation.scala @@ -0,0 +1,202 @@ +package org.openapitools.client.api + +import org.openapitools.client.model._ +import com.typesafe.config.ConfigFactory + +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import io.gatling.core.structure.PopulationBuilder + +import java.io.File + +import scala.collection.mutable + +class UserApiSimulation extends Simulation { + + def getCurrentDirectory = new File("").getAbsolutePath + def userDataDirectory = getCurrentDirectory + "/src/gatling/resources/data" + + // basic test setup + val configName = System.getProperty("testConfig", "baseline") + val config = ConfigFactory.load(configName).withFallback(ConfigFactory.load("default")) + val durationSeconds = config.getInt("performance.durationSeconds") + val rampUpSeconds = config.getInt("performance.rampUpSeconds") + val rampDownSeconds = config.getInt("performance.rampDownSeconds") + val authentication = config.getString("performance.authorizationHeader") + val acceptHeader = config.getString("performance.acceptType") + val contentTypeHeader = config.getString("performance.contentType") + val rateMultiplier = config.getDouble("performance.rateMultiplier") + val instanceMultiplier = config.getDouble("performance.instanceMultiplier") + + // global assertion data + val globalResponseTimeMinLTE = config.getInt("performance.global.assertions.responseTime.min.lte") + val globalResponseTimeMinGTE = config.getInt("performance.global.assertions.responseTime.min.gte") + val globalResponseTimeMaxLTE = config.getInt("performance.global.assertions.responseTime.max.lte") + val globalResponseTimeMaxGTE = config.getInt("performance.global.assertions.responseTime.max.gte") + val globalResponseTimeMeanLTE = config.getInt("performance.global.assertions.responseTime.mean.lte") + val globalResponseTimeMeanGTE = config.getInt("performance.global.assertions.responseTime.mean.gte") + val globalResponseTimeFailedRequestsPercentLTE = config.getDouble("performance.global.assertions.failedRequests.percent.lte") + val globalResponseTimeFailedRequestsPercentGTE = config.getDouble("performance.global.assertions.failedRequests.percent.gte") + val globalResponseTimeSuccessfulRequestsPercentLTE = config.getDouble("performance.global.assertions.successfulRequests.percent.lte") + val globalResponseTimeSuccessfulRequestsPercentGTE = config.getDouble("performance.global.assertions.successfulRequests.percent.gte") + +// Setup http protocol configuration + val httpConf = http + .baseURL("http://petstore.swagger.io/v2") + .doNotTrackHeader("1") + .acceptLanguageHeader("en-US,en;q=0.5") + .acceptEncodingHeader("gzip, deflate") + .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") + .acceptHeader(acceptHeader) + .contentTypeHeader(contentTypeHeader) + + // set authorization header if it has been modified from config + if(!authentication.equals("~MANUAL_ENTRY")){ + httpConf.authorizationHeader(authentication) + } + + // Setup all the operations per second for the test to ultimately be generated from configs + val createUserPerSecond = config.getDouble("performance.operationsPerSecond.createUser") * rateMultiplier * instanceMultiplier + val createUsersWithArrayInputPerSecond = config.getDouble("performance.operationsPerSecond.createUsersWithArrayInput") * rateMultiplier * instanceMultiplier + val createUsersWithListInputPerSecond = config.getDouble("performance.operationsPerSecond.createUsersWithListInput") * rateMultiplier * instanceMultiplier + val deleteUserPerSecond = config.getDouble("performance.operationsPerSecond.deleteUser") * rateMultiplier * instanceMultiplier + val getUserByNamePerSecond = config.getDouble("performance.operationsPerSecond.getUserByName") * rateMultiplier * instanceMultiplier + val loginUserPerSecond = config.getDouble("performance.operationsPerSecond.loginUser") * rateMultiplier * instanceMultiplier + val logoutUserPerSecond = config.getDouble("performance.operationsPerSecond.logoutUser") * rateMultiplier * instanceMultiplier + val updateUserPerSecond = config.getDouble("performance.operationsPerSecond.updateUser") * rateMultiplier * instanceMultiplier + + val scenarioBuilders: mutable.MutableList[PopulationBuilder] = new mutable.MutableList[PopulationBuilder]() + + // Set up CSV feeders + val deleteUserPATHFeeder = csv(userDataDirectory + File.separator + "deleteUser-pathParams.csv").random + val getUserByNamePATHFeeder = csv(userDataDirectory + File.separator + "getUserByName-pathParams.csv").random + val loginUserQUERYFeeder = csv(userDataDirectory + File.separator + "loginUser-queryParams.csv").random + val updateUserPATHFeeder = csv(userDataDirectory + File.separator + "updateUser-pathParams.csv").random + + // Setup all scenarios + + + val scncreateUser = scenario("createUserSimulation") + .exec(http("createUser") + .httpRequest("POST","/user") +) + + // Run scncreateUser with warm up and reach a constant rate for entire duration + scenarioBuilders += scncreateUser.inject( + rampUsersPerSec(1) to(createUserPerSecond) during(rampUpSeconds), + constantUsersPerSec(createUserPerSecond) during(durationSeconds), + rampUsersPerSec(createUserPerSecond) to(1) during(rampDownSeconds) + ) + + + val scncreateUsersWithArrayInput = scenario("createUsersWithArrayInputSimulation") + .exec(http("createUsersWithArrayInput") + .httpRequest("POST","/user/createWithArray") +) + + // Run scncreateUsersWithArrayInput with warm up and reach a constant rate for entire duration + scenarioBuilders += scncreateUsersWithArrayInput.inject( + rampUsersPerSec(1) to(createUsersWithArrayInputPerSecond) during(rampUpSeconds), + constantUsersPerSec(createUsersWithArrayInputPerSecond) during(durationSeconds), + rampUsersPerSec(createUsersWithArrayInputPerSecond) to(1) during(rampDownSeconds) + ) + + + val scncreateUsersWithListInput = scenario("createUsersWithListInputSimulation") + .exec(http("createUsersWithListInput") + .httpRequest("POST","/user/createWithList") +) + + // Run scncreateUsersWithListInput with warm up and reach a constant rate for entire duration + scenarioBuilders += scncreateUsersWithListInput.inject( + rampUsersPerSec(1) to(createUsersWithListInputPerSecond) during(rampUpSeconds), + constantUsersPerSec(createUsersWithListInputPerSecond) during(durationSeconds), + rampUsersPerSec(createUsersWithListInputPerSecond) to(1) during(rampDownSeconds) + ) + + + val scndeleteUser = scenario("deleteUserSimulation") + .feed(deleteUserPATHFeeder) + .exec(http("deleteUser") + .httpRequest("DELETE","/user/${username}") +) + + // Run scndeleteUser with warm up and reach a constant rate for entire duration + scenarioBuilders += scndeleteUser.inject( + rampUsersPerSec(1) to(deleteUserPerSecond) during(rampUpSeconds), + constantUsersPerSec(deleteUserPerSecond) during(durationSeconds), + rampUsersPerSec(deleteUserPerSecond) to(1) during(rampDownSeconds) + ) + + + val scngetUserByName = scenario("getUserByNameSimulation") + .feed(getUserByNamePATHFeeder) + .exec(http("getUserByName") + .httpRequest("GET","/user/${username}") +) + + // Run scngetUserByName with warm up and reach a constant rate for entire duration + scenarioBuilders += scngetUserByName.inject( + rampUsersPerSec(1) to(getUserByNamePerSecond) during(rampUpSeconds), + constantUsersPerSec(getUserByNamePerSecond) during(durationSeconds), + rampUsersPerSec(getUserByNamePerSecond) to(1) during(rampDownSeconds) + ) + + + val scnloginUser = scenario("loginUserSimulation") + .feed(loginUserQUERYFeeder) + .exec(http("loginUser") + .httpRequest("GET","/user/login") + .queryParam("username","${username}") + .queryParam("password","${password}") +) + + // Run scnloginUser with warm up and reach a constant rate for entire duration + scenarioBuilders += scnloginUser.inject( + rampUsersPerSec(1) to(loginUserPerSecond) during(rampUpSeconds), + constantUsersPerSec(loginUserPerSecond) during(durationSeconds), + rampUsersPerSec(loginUserPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnlogoutUser = scenario("logoutUserSimulation") + .exec(http("logoutUser") + .httpRequest("GET","/user/logout") +) + + // Run scnlogoutUser with warm up and reach a constant rate for entire duration + scenarioBuilders += scnlogoutUser.inject( + rampUsersPerSec(1) to(logoutUserPerSecond) during(rampUpSeconds), + constantUsersPerSec(logoutUserPerSecond) during(durationSeconds), + rampUsersPerSec(logoutUserPerSecond) to(1) during(rampDownSeconds) + ) + + + val scnupdateUser = scenario("updateUserSimulation") + .feed(updateUserPATHFeeder) + .exec(http("updateUser") + .httpRequest("PUT","/user/${username}") +) + + // Run scnupdateUser with warm up and reach a constant rate for entire duration + scenarioBuilders += scnupdateUser.inject( + rampUsersPerSec(1) to(updateUserPerSecond) during(rampUpSeconds), + constantUsersPerSec(updateUserPerSecond) during(durationSeconds), + rampUsersPerSec(updateUserPerSecond) to(1) during(rampDownSeconds) + ) + + setUp( + scenarioBuilders.toList + ).protocols(httpConf).assertions( + global.responseTime.min.lte(globalResponseTimeMinLTE), + global.responseTime.min.gte(globalResponseTimeMinGTE), + global.responseTime.max.lte(globalResponseTimeMaxLTE), + global.responseTime.max.gte(globalResponseTimeMaxGTE), + global.responseTime.mean.lte(globalResponseTimeMeanLTE), + global.responseTime.mean.gte(globalResponseTimeMeanGTE), + global.failedRequests.percent.lte(globalResponseTimeFailedRequestsPercentLTE), + global.failedRequests.percent.gte(globalResponseTimeFailedRequestsPercentGTE), + global.successfulRequests.percent.lte(globalResponseTimeSuccessfulRequestsPercentLTE), + global.successfulRequests.percent.gte(globalResponseTimeSuccessfulRequestsPercentGTE) + ) +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/ApiResponse.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/ApiResponse.scala new file mode 100644 index 000000000000..27d53614c6e2 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/ApiResponse.scala @@ -0,0 +1,17 @@ + +package org.openapitools.client.model + + +case class ApiResponse ( + _code: Option[Integer], + _type: Option[String], + _message: Option[String] +) +object ApiResponse { + def toStringBody(var_code: Object, var_type: Object, var_message: Object) = + s""" + | { + | "code":$var_code,"type":$var_type,"message":$var_message + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Category.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Category.scala new file mode 100644 index 000000000000..02e43d9b0dd3 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Category.scala @@ -0,0 +1,16 @@ + +package org.openapitools.client.model + + +case class Category ( + _id: Option[Long], + _name: Option[String] +) +object Category { + def toStringBody(var_id: Object, var_name: Object) = + s""" + | { + | "id":$var_id,"name":$var_name + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Order.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Order.scala new file mode 100644 index 000000000000..ba6967f0e176 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Order.scala @@ -0,0 +1,22 @@ + +package org.openapitools.client.model + +import java.util.Date + +case class Order ( + _id: Option[Long], + _petId: Option[Long], + _quantity: Option[Integer], + _shipDate: Option[Date], + /* Order Status */ + _status: Option[String], + _complete: Option[Boolean] +) +object Order { + def toStringBody(var_id: Object, var_petId: Object, var_quantity: Object, var_shipDate: Object, var_status: Object, var_complete: Object) = + s""" + | { + | "id":$var_id,"petId":$var_petId,"quantity":$var_quantity,"shipDate":$var_shipDate,"status":$var_status,"complete":$var_complete + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Pet.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Pet.scala new file mode 100644 index 000000000000..6f5800852870 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Pet.scala @@ -0,0 +1,21 @@ + +package org.openapitools.client.model + + +case class Pet ( + _id: Option[Long], + _category: Option[Category], + _name: String, + _photoUrls: List[String], + _tags: Option[List[Tag]], + /* pet status in the store */ + _status: Option[String] +) +object Pet { + def toStringBody(var_id: Object, var_category: Object, var_name: Object, var_photoUrls: Object, var_tags: Object, var_status: Object) = + s""" + | { + | "id":$var_id,"category":$var_category,"name":$var_name,"photoUrls":$var_photoUrls,"tags":$var_tags,"status":$var_status + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Tag.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Tag.scala new file mode 100644 index 000000000000..2b8c033de86a --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/Tag.scala @@ -0,0 +1,16 @@ + +package org.openapitools.client.model + + +case class Tag ( + _id: Option[Long], + _name: Option[String] +) +object Tag { + def toStringBody(var_id: Object, var_name: Object) = + s""" + | { + | "id":$var_id,"name":$var_name + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/User.scala b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/User.scala new file mode 100644 index 000000000000..64607788b280 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/org/openapitools/client/model/User.scala @@ -0,0 +1,23 @@ + +package org.openapitools.client.model + + +case class User ( + _id: Option[Long], + _username: Option[String], + _firstName: Option[String], + _lastName: Option[String], + _email: Option[String], + _password: Option[String], + _phone: Option[String], + /* User Status */ + _userStatus: Option[Integer] +) +object User { + def toStringBody(var_id: Object, var_username: Object, var_firstName: Object, var_lastName: Object, var_email: Object, var_password: Object, var_phone: Object, var_userStatus: Object) = + s""" + | { + | "id":$var_id,"username":$var_username,"firstName":$var_firstName,"lastName":$var_lastName,"email":$var_email,"password":$var_password,"phone":$var_phone,"userStatus":$var_userStatus + | } + """.stripMargin +} diff --git a/samples/client/petstore/scala-gatling/bin/gatling/placeOrder-BodyParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/placeOrder-BodyParams.csv new file mode 100644 index 000000000000..a2fe128b281c --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/placeOrder-BodyParams.csv @@ -0,0 +1 @@ +petId,quantity,id,shipDate,complete,status \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/stress.conf b/samples/client/petstore/scala-gatling/bin/gatling/stress.conf new file mode 100644 index 000000000000..1d75d0e40f94 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/stress.conf @@ -0,0 +1,62 @@ +performance { + authorizationHeader = "~MANUAL_ENTRY~" + rampUpSeconds = 60 + rampDownSeconds = 60 + durationSeconds = 360 + contentType = "application/json" + acceptType = "application/json" + rateMultiplier = 1 + instanceMultiplier = 1 + operationsPerSecond { + addPet = 1 + deletePet = 1 + findPetsByStatus = 1 + findPetsByTags = 1 + getPetById = 1 + updatePet = 1 + updatePetWithForm = 1 + uploadFile = 1 + deleteOrder = 1 + getInventory = 1 + getOrderById = 1 + placeOrder = 1 + createUser = 1 + createUsersWithArrayInput = 1 + createUsersWithListInput = 1 + deleteUser = 1 + getUserByName = 1 + loginUser = 1 + logoutUser = 1 + updateUser = 1 + } + global { + assertions { + responseTime { + min { + lte = 30000 + gte = 0 + } + max { + lte = 30000 + gte = 0 + } + mean { + lte = 30000 + gte = 0 + } + } + failedRequests { + percent { + lte = 5 + gte = 0 + } + } + successfulRequests { + percent { + lte = 100 + gte = 0 + } + } + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/updatePet-BodyParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/updatePet-BodyParams.csv new file mode 100644 index 000000000000..9c23144ca977 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/updatePet-BodyParams.csv @@ -0,0 +1 @@ +photoUrls,name,id,category,tags,status \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-formParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-formParams.csv new file mode 100644 index 000000000000..14cb48cc6be6 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-formParams.csv @@ -0,0 +1 @@ +name,status \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-pathParams.csv new file mode 100644 index 000000000000..45e87671b9aa --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/updatePetWithForm-pathParams.csv @@ -0,0 +1 @@ +petId \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/updateUser-BodyParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/updateUser-BodyParams.csv new file mode 100644 index 000000000000..38dcc63f0202 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/updateUser-BodyParams.csv @@ -0,0 +1 @@ +firstName,lastName,password,userStatus,phone,id,email,username \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/updateUser-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/updateUser-pathParams.csv new file mode 100644 index 000000000000..22947b68d01c --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/updateUser-pathParams.csv @@ -0,0 +1 @@ +username \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-formParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-formParams.csv new file mode 100644 index 000000000000..50f9afc8d6c8 --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-formParams.csv @@ -0,0 +1 @@ +file,additionalMetadata \ No newline at end of file diff --git a/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-pathParams.csv b/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-pathParams.csv new file mode 100644 index 000000000000..45e87671b9aa --- /dev/null +++ b/samples/client/petstore/scala-gatling/bin/gatling/uploadFile-pathParams.csv @@ -0,0 +1 @@ +petId \ No newline at end of file diff --git a/samples/client/petstore/scala-httpclient/bin/PetApiTest.scala b/samples/client/petstore/scala-httpclient/bin/PetApiTest.scala new file mode 100644 index 000000000000..e75dae01493b --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/PetApiTest.scala @@ -0,0 +1,94 @@ +import org.openapitools.client._ +import org.openapitools.client.api._ +import org.openapitools.client.model._ + +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest._ + +import scala.collection.mutable.{ ListBuffer, HashMap } +import scala.collection.JavaConverters._ +import scala.beans.BeanProperty + +@RunWith(classOf[JUnitRunner]) +class PetApiTest extends FlatSpec with Matchers { + behavior of "PetApi" + val api = new PetApi + + it should "add and fetch a pet" in { + val pet = Pet( + Some(1000), + Some(Category(Some(1), Some("sold"))), + "dragon", + (for (i <- (1 to 10)) yield "http://foo.com/photo/" + i).toList, + Some((for (i <- (1 to 5)) yield org.openapitools.client.model.Tag(Some(i), Some("tag-" + i))).toList), + Some("lost") + ) + + api.addPet(pet) + api.getPetById(1000) match { + case Some(pet) => { + pet.id should be(Some(1000)) + pet.tags.get.size should be(5) + pet.status should be(Some("lost")) + pet.category should not be (null) + pet.category.get.name should be(Some("sold")) + pet.name should be("dragon") + pet.photoUrls.size should be(10) + } + case None => fail("didn't find pet created") + } + } + + it should "update a pet" in { + val pet = Pet( + Some(1000), + Some(Category(Some(1), Some("sold"))), + "programmer", + (for (i <- (1 to 10)) yield "http://foo.com/photo/" + i).toList, + Some((for (i <- (1 to 5)) yield org.openapitools.client.model.Tag(Some(i), Some("tag-" + i))).toList), + Some("confused") + ) + + api.addPet(pet) + + api.getPetById(1000) match { + case Some(pet) => { + pet.name should be("programmer") + pet.status should be(Some("confused")) + } + case None => fail("didn't find pet created") + } + val updatedPet = pet.copy(status = Some("fulfilled")) + api.updatePet(updatedPet) + api.getPetById(1000) match { + case Some(pet) => { + pet.name should be("programmer") + pet.status should be(Some("fulfilled")) + } + case None => fail("didn't find pet updated") + } + } + + it should "find pets by status" in { + api.findPetsByStatus(List("available")) match { + case Some(pets) => { + pets.foreach(pet => pet.status should be("available")) + } + case None => fail("didn't find pets by status") + } + } + + it should "find pets by tag" in { + api.findPetsByTags(List("tag1", "tag2")) match { + case Some(pets) => { + pets.foreach(pet => { + val tags = (for (tag <- pet.tags.get) yield tag.name).toSet + if ((tags & Set(Some("tag1"), Some("tag2"))).size == 0) + fail("unexpected tags in " + tags) + }) + } + case None => fail("didn't find pets by tag") + } + } +} diff --git a/samples/client/petstore/scala-httpclient/bin/StoreApiTest.scala b/samples/client/petstore/scala-httpclient/bin/StoreApiTest.scala new file mode 100644 index 000000000000..29cdaec593f1 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/StoreApiTest.scala @@ -0,0 +1,71 @@ +import org.openapitools.client._ +import org.openapitools.client.api._ +import org.openapitools.client.model._ +import org.joda.time.DateTime + +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest._ + +import scala.collection.mutable.{ ListBuffer, HashMap } +import scala.collection.JavaConverters._ +import scala.beans.BeanProperty +import java.util.Date + +@RunWith(classOf[JUnitRunner]) +class StoreApiTest extends FlatSpec with Matchers { + behavior of "StoreApi" + val api = new StoreApi + + api.apiInvoker.defaultHeaders += "api_key" -> "special-key" + + it should "place and fetch an order" in { + val now = new Date() + val order = Order( + petId = Some(10), + id = Some(1000), + quantity = Some(101), + status = Some("pending"), + shipDate = Some(now), + complete = Some(true)) + + api.placeOrder(order) + + api.getOrderById(1000) match { + case Some(order) => { + order.id.get should be(1000) + order.petId.get should be(10) + order.quantity.get should be(101) + order.shipDate.get.getTime().equals(now.getTime()) should be(true) + } + case None => fail("didn't find order created") + } + } + + it should "delete an order" in { + val now = new Date() + val order = Order( + id = Some(1001), + petId = Some(10), + quantity = Some(101), + status = Some("pending"), + shipDate = Some(now), + complete = Some(true)) + + api.placeOrder(order) + + api.getOrderById(1001) match { + case Some(order) => order.id should be(Some(1001)) + case None => fail("didn't find order created") + } + + api.deleteOrder("1001") + /* comment out the following as the client cannot handle + * 4xx response yet + api.getOrderById(1001) match { + case Some(order) => fail("order should have been deleted") + case None => + } + */ + } +} diff --git a/samples/client/petstore/scala-httpclient/bin/UserApiTest.scala b/samples/client/petstore/scala-httpclient/bin/UserApiTest.scala new file mode 100644 index 000000000000..a7942a788d9c --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/UserApiTest.scala @@ -0,0 +1,150 @@ +import org.openapitools.client._ +import org.openapitools.client.api._ +import org.openapitools.client.model._ + +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest._ + +import scala.collection.mutable.{ ListBuffer, HashMap } +import scala.collection.JavaConverters._ +import scala.beans.BeanProperty + +@RunWith(classOf[JUnitRunner]) +class UserApiTest extends FlatSpec with Matchers with BeforeAndAfterAll { + behavior of "UserApi" + val api = new UserApi + api.apiInvoker.defaultHeaders += "api_key" -> "special-key" + + // preparation before running a test + override def beforeAll() { + val user = User( + Some(11222), + Some("scala-test-username"), + Some("scala-test-first"), + Some("scala-test-last"), + Some("scala_test@fail.com"), + Some("SCALATEST"), + Some("408-867-5309"), + Some(1)) + + api.createUser(user) + } + + // cleanup after running a test + override def afterAll() { + api.deleteUser("scala-test-username") + } + + it should "fetch a user" in { + api.getUserByName("scala-test-username") match { + case Some(user) => { + user.id should be(Some(11222)) + user.username should be(Some("scala-test-username")) + user.password should be(Some("SCALATEST")) + user.email should be(Some("scala_test@fail.com")) + user.firstName should be(Some("scala-test-first")) + user.lastName should be(Some("scala-test-last")) + user.phone should be(Some("408-867-5309")) + user.userStatus should be(Some(1)) + } + case None => + } + } + + it should "authenticate a user" in { + api.loginUser("scala-test-username", "SCALATEST") match { + case Some(status) => status.startsWith("logged in user session") match { + case true => // success! + case _ => fail("didn't get expected message " + status) + } + case None => fail("not able to login") + } + } + + it should "log out a user" in { + api.logoutUser + } + + it should "create 2 users" in { + val userArray = (for (i <- (1 to 2)) yield { + User( + Some(2000 + i), + Some("johnny-" + i), + Some("Johnny"), + Some("Rocket-" + i), + Some("johnny-" + i + "@fail.com"), + Some("XXXXXXXXXXX"), + Some("408-867-5309"), + Some(1)) + }).toList + api.createUsersWithArrayInput(userArray) + + for (i <- (1 to 2)) { + api.getUserByName("johnny-" + i) match { + case Some(user) => { + user.id should be(Some(2000 + i)) + user.email should be(Some("johnny-" + i + "@fail.com")) + } + case None => fail("didn't find user " + i) + } + } + } + + it should "create 3 users" in { + val userList = (for (i <- (1 to 3)) yield { + User( + Some(3000 + i), + Some("fred-" + i), + Some("Johnny"), + Some("Rocket-" + i), + Some("fred-" + i + "@fail.com"), + Some("XXXXXXXXXXX"), + Some("408-867-5309"), + Some(1)) + }).toList + api.createUsersWithListInput(userList) + + for (i <- (1 to 3)) { + api.getUserByName("fred-" + i) match { + case Some(user) => { + user.id should be(Some(3000 + i)) + user.email should be(Some("fred-" + i + "@fail.com")) + } + case None => fail("didn't find user " + i) + } + } + } + + it should "update a user" in { + val user = User( + Some(4000), + Some("tony"), + Some("Tony"), + Some("Tiger"), + Some("tony@fail.com"), + Some("XXXXXXXXXXX"), + Some("408-867-5309"), + Some(1)) + + api.createUser(user) + + api.getUserByName("tony") match { + case Some(user) => { + user.id should be(Some(4000)) + user.username should be(Some("tony")) + } + case None => + } + + val updatedUser = user.copy(email = Some("tony@succeed.com")) + + api.updateUser("tony", updatedUser) + api.getUserByName("tony") match { + case Some(user) => { + user.email should be(Some("tony@succeed.com")) + } + case None => + } + } +} diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/ApiInvoker.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/ApiInvoker.scala new file mode 100644 index 000000000000..885c71199db3 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/ApiInvoker.scala @@ -0,0 +1,237 @@ +/** + * 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. + * + * OpenAPI spec version: 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 + +import com.sun.jersey.api.client.Client +import com.sun.jersey.api.client.ClientResponse +import com.sun.jersey.api.client.config.ClientConfig +import com.sun.jersey.api.client.config.DefaultClientConfig +import com.sun.jersey.api.client.filter.LoggingFilter + +import com.sun.jersey.core.util.MultivaluedMapImpl +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart + +import java.io.File +import java.net.URLEncoder +import java.util.UUID +import javax.ws.rs.core.MediaType + +import scala.collection.JavaConverters._ +import scala.collection.mutable + +import com.fasterxml.jackson.module.scala.DefaultScalaModule +import com.fasterxml.jackson.datatype.joda.JodaModule +import com.fasterxml.jackson.core.JsonGenerator.Feature +import com.fasterxml.jackson.databind._ +import com.fasterxml.jackson.annotation._ +import com.fasterxml.jackson.databind.annotation.JsonSerialize + +object ScalaJsonUtil { + def getJsonMapper: ObjectMapper = { + val mapper = new ObjectMapper() + mapper.registerModule(new DefaultScalaModule()) + mapper.registerModule(new JodaModule()) + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) + mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT) + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY) + mapper + } +} + +class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, + httpHeaders: mutable.HashMap[String, String] = mutable.HashMap(), + hostMap: mutable.HashMap[String, Client] = mutable.HashMap(), + asyncHttpClient: Boolean = false, + authScheme: String = "", + authPreemptive: Boolean = false +) { + + var defaultHeaders: mutable.HashMap[String, String] = httpHeaders + + def escape(value: String): String = { + URLEncoder.encode(value, "utf-8").replaceAll("\\+", "%20") + } + def escape(values: List[String]): String = { + values.map(escape).mkString(",") + } + + def escape(value: Long): String = value.toString + def escape(value: Double): String = value.toString + def escape(value: Float): String = value.toString + def escape(value: UUID): String = value.toString + + def deserialize(json: String, containerType: String, cls: Class[_]) = { + if (cls == classOf[String]) { + json match { + case s: String => + if (s.startsWith("\"") && s.endsWith("\"") && s.length > 1) { + s.substring(1, s.length - 1) + } else { + s + } + case _ => null + } + } else { + containerType.toLowerCase match { + case "array" => + val typeInfo = mapper.getTypeFactory.constructCollectionType(classOf[java.util.List[_]], cls) + val response = mapper.readValue(json, typeInfo).asInstanceOf[java.util.List[_]] + response.asScala.toList + case "list" => + val typeInfo = mapper.getTypeFactory.constructCollectionType(classOf[java.util.List[_]], cls) + val response = mapper.readValue(json, typeInfo).asInstanceOf[java.util.List[_]] + response.asScala.toList + case _ => + json match { + case e: String if "\"\"" == e => null + case _ => mapper.readValue(json, cls) + } + } + } + } + + def serialize(obj: AnyRef): String = { + if (obj != null) { + obj match { + case e: List[_] => mapper.writeValueAsString(obj.asInstanceOf[List[_]].asJava) + case _ => mapper.writeValueAsString(obj) + } + } else { + null + } + } + + def invokeApi( + host: String, + path: String, + method: String, + queryParams: Map[String, String], + formParams: Map[String, String], + body: AnyRef, + headerParams: Map[String, String], + contentType: String +): String = { + val client = getClient(host) + + val querystring = queryParams.filter(k => k._2 != null).map(k => escape(k._1) + "=" + escape(k._2)).mkString("?", "&", "") + val builder = client.resource(host + path + querystring).accept(contentType) + headerParams.map(p => builder.header(p._1, p._2)) + defaultHeaders.foreach(p => { + if (!headerParams.contains(p._1) && p._2 != null) { + builder.header(p._1, p._2) + } + }) + var formData: MultivaluedMapImpl = null + if (contentType == "application/x-www-form-urlencoded") { + formData = new MultivaluedMapImpl() + formParams.foreach(p => formData.add(p._1, p._2)) + } + + val response: ClientResponse = method match { + case "GET" => builder.get(classOf[ClientResponse]) + case "POST" => + if (formData != null && formData.size() > 0) { + builder.post(classOf[ClientResponse], formData) + } else if (body != null && body.isInstanceOf[File]) { + val file = body.asInstanceOf[File] + val form = new FormDataMultiPart() + form.field("filename", file.getName) + form.bodyPart(new FileDataBodyPart("file", file, MediaType.MULTIPART_FORM_DATA_TYPE)) + builder.post(classOf[ClientResponse], form) + } else { + if (body == null) { + builder.post(classOf[ClientResponse], serialize(body)) + } else { + builder.`type`(contentType).post(classOf[ClientResponse], serialize(body)) + } + } + case "PUT" => + if (formData != null) { + builder.post(classOf[ClientResponse], formData) + } else if (body == null) { + builder.put(classOf[ClientResponse], null) + } else { + builder.`type`(contentType).put(classOf[ClientResponse], serialize(body)) + } + case "DELETE" => builder.delete(classOf[ClientResponse]) + case "PATCH" => + if(formData != null) { + builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], formData) + } else if(body == null) { + builder.header("X-HTTP-Method-Override", "PATCH").post(classOf[ClientResponse], null) + } else { + builder.header("X-HTTP-Method-Override", "PATCH").`type`(contentType).post(classOf[ClientResponse], serialize(body)) + } + case _ => null + } + response.getStatusInfo.getStatusCode match { + case 204 => "" + case code: Int if Range(200, 299).contains(code) => + if (response.hasEntity) { + response.getEntity(classOf[String]) + } else { + "" + } + case _ => + val entity = if (response.hasEntity) { + response.getEntity(classOf[String]) + } else { + "no data" + } + throw new ApiException(response.getStatusInfo.getStatusCode, entity) + } + } + + def getClient(host: String): Client = { + if (hostMap.contains(host)) { + hostMap(host) + } else { + val client = newClient(host) + // client.addFilter(new LoggingFilter()) + hostMap += host -> client + client + } + } + + def newClient(host: String): Client = if (asyncHttpClient) { + import com.ning.http.client.Realm + import org.sonatype.spice.jersey.client.ahc.AhcHttpClient + import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig + + val config: DefaultAhcConfig = new DefaultAhcConfig() + if (!authScheme.isEmpty) { + val authSchemeEnum = Realm.AuthScheme.valueOf(authScheme) + config + .getAsyncHttpClientConfigBuilder + .setRealm(new Realm.RealmBuilder().setScheme(authSchemeEnum) + .setUsePreemptiveAuth(authPreemptive).build) + } + AhcHttpClient.create(config) + } else { + Client.create() + } +} + +object ApiInvoker extends ApiInvoker( + mapper = ScalaJsonUtil.getJsonMapper, + httpHeaders = mutable.HashMap(), + hostMap = mutable.HashMap(), + asyncHttpClient = false, + authScheme = "", + authPreemptive = false +) + +class ApiException(val code: Int, msg: String) extends RuntimeException(msg) diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/AsyncClient.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/AsyncClient.scala new file mode 100644 index 000000000000..2cb5c7f5d2d8 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/AsyncClient.scala @@ -0,0 +1,20 @@ +package org.openapitools.client + +import org.openapitools.client.api._ + +import com.wordnik.swagger.client._ + +import java.io.Closeable + +class AsyncClient(config: SwaggerConfig) extends Closeable { + lazy val locator: ServiceLocator = config.locator + lazy val name: String = config.name + + private[this] val client = transportClient + + protected def transportClient: TransportClient = new RestClient(config) + + def close() { + client.close() + } +} diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/PetApi.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/PetApi.scala new file mode 100644 index 000000000000..191e9f9fa4b8 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/PetApi.scala @@ -0,0 +1,443 @@ +/** + * 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. + * + * OpenAPI spec version: 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 java.text.SimpleDateFormat + +import org.openapitools.client.model.ApiResponse +import java.io.File +import org.openapitools.client.model.Pet +import org.openapitools.client.{ApiInvoker, ApiException} + +import collection.mutable +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart +import com.wordnik.swagger.client._ +import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._ +import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._ + +import java.net.URI +import java.io.File +import java.util.Date +import java.util.TimeZone +import javax.ws.rs.core.MediaType + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.collection.mutable.HashMap +import scala.util.{Failure, Success, Try} + +import org.json4s._ + +class PetApi( + val defBasePath: String = "http://petstore.swagger.io/v2", + defApiInvoker: ApiInvoker = ApiInvoker +) { + private lazy val dateTimeFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + private val dateFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + implicit val formats = new org.json4s.DefaultFormats { + override def dateFormatter = dateTimeFormatter + } + implicit val stringReader: ClientResponseReader[String] = ClientResponseReaders.StringReader + implicit val unitReader: ClientResponseReader[Unit] = ClientResponseReaders.UnitReader + implicit val jvalueReader: ClientResponseReader[JValue] = ClientResponseReaders.JValueReader + implicit val jsonReader: ClientResponseReader[Nothing] = JsonFormatsReader + implicit val stringWriter: RequestWriter[String] = RequestWriters.StringWriter + implicit val jsonWriter: RequestWriter[Nothing] = JsonFormatsWriter + + var basePath: String = defBasePath + var apiInvoker: ApiInvoker = defApiInvoker + + def addHeader(key: String, value: String): mutable.HashMap[String, String] = { + apiInvoker.defaultHeaders += key -> value + } + + val config: SwaggerConfig = SwaggerConfig.forUrl(new URI(defBasePath)) + val client = new RestClient(config) + val helper = new PetApiAsyncHelper(client, config) + + /** + * Add a new pet to the store + * + * + * @param body Pet object that needs to be added to the store + * @return void + */ + def addPet(body: Pet) = { + val await = Try(Await.result(addPetAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Add a new pet to the store asynchronously + * + * + * @param body Pet object that needs to be added to the store + * @return Future(void) + */ + def addPetAsync(body: Pet) = { + helper.addPet(body) + } + + /** + * Deletes a pet + * + * + * @param petId Pet id to delete + * @param apiKey (optional) + * @return void + */ + def deletePet(petId: Long, apiKey: Option[String] = None) = { + val await = Try(Await.result(deletePetAsync(petId, apiKey), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Deletes a pet asynchronously + * + * + * @param petId Pet id to delete + * @param apiKey (optional) + * @return Future(void) + */ + def deletePetAsync(petId: Long, apiKey: Option[String] = None) = { + helper.deletePet(petId, apiKey) + } + + /** + * Finds Pets by status + * Multiple status values can be provided with comma separated strings + * + * @param status Status values that need to be considered for filter + * @return List[Pet] + */ + def findPetsByStatus(status: List[String]): Option[List[Pet]] = { + val await = Try(Await.result(findPetsByStatusAsync(status), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Finds Pets by status asynchronously + * Multiple status values can be provided with comma separated strings + * + * @param status Status values that need to be considered for filter + * @return Future(List[Pet]) + */ + def findPetsByStatusAsync(status: List[String]): Future[List[Pet]] = { + helper.findPetsByStatus(status) + } + + /** + * Finds Pets by tags + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * + * @param tags Tags to filter by + * @return List[Pet] + */ + def findPetsByTags(tags: List[String]): Option[List[Pet]] = { + val await = Try(Await.result(findPetsByTagsAsync(tags), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Finds Pets by tags asynchronously + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * + * @param tags Tags to filter by + * @return Future(List[Pet]) + */ + def findPetsByTagsAsync(tags: List[String]): Future[List[Pet]] = { + helper.findPetsByTags(tags) + } + + /** + * Find pet by ID + * Returns a single pet + * + * @param petId ID of pet to return + * @return Pet + */ + def getPetById(petId: Long): Option[Pet] = { + val await = Try(Await.result(getPetByIdAsync(petId), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Find pet by ID asynchronously + * Returns a single pet + * + * @param petId ID of pet to return + * @return Future(Pet) + */ + def getPetByIdAsync(petId: Long): Future[Pet] = { + helper.getPetById(petId) + } + + /** + * Update an existing pet + * + * + * @param body Pet object that needs to be added to the store + * @return void + */ + def updatePet(body: Pet) = { + val await = Try(Await.result(updatePetAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Update an existing pet asynchronously + * + * + * @param body Pet object that needs to be added to the store + * @return Future(void) + */ + def updatePetAsync(body: Pet) = { + helper.updatePet(body) + } + + /** + * Updates a pet in the store with form data + * + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet (optional) + * @param status Updated status of the pet (optional) + * @return void + */ + def updatePetWithForm(petId: Long, name: Option[String] = None, status: Option[String] = None) = { + val await = Try(Await.result(updatePetWithFormAsync(petId, name, status), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Updates a pet in the store with form data asynchronously + * + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet (optional) + * @param status Updated status of the pet (optional) + * @return Future(void) + */ + def updatePetWithFormAsync(petId: Long, name: Option[String] = None, status: Option[String] = None) = { + helper.updatePetWithForm(petId, name, status) + } + + /** + * uploads an image + * + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server (optional) + * @param file file to upload (optional) + * @return ApiResponse + */ + def uploadFile(petId: Long, additionalMetadata: Option[String] = None, file: Option[File] = None): Option[ApiResponse] = { + val await = Try(Await.result(uploadFileAsync(petId, additionalMetadata, file), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * uploads an image asynchronously + * + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server (optional) + * @param file file to upload (optional) + * @return Future(ApiResponse) + */ + def uploadFileAsync(petId: Long, additionalMetadata: Option[String] = None, file: Option[File] = None): Future[ApiResponse] = { + helper.uploadFile(petId, additionalMetadata, file) + } + +} + +class PetApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) { + + def addPet(body: Pet)(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[Pet]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/pet")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling PetApi->addPet") + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def deletePet(petId: Long, + apiKey: Option[String] = None + )(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/pet/{petId}") + replaceAll("\\{" + "petId" + "\\}", petId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + apiKey match { + case Some(param) => headerParams += "api_key" -> param.toString + case _ => headerParams + } + + val resFuture = client.submit("DELETE", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def findPetsByStatus(status: List[String])(implicit reader: ClientResponseReader[List[Pet]]): Future[List[Pet]] = { + // create path and map variables + val path = (addFmt("/pet/findByStatus")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (status == null) throw new Exception("Missing required parameter 'status' when calling PetApi->findPetsByStatus") + queryParams += "status" -> status.toString + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def findPetsByTags(tags: List[String])(implicit reader: ClientResponseReader[List[Pet]]): Future[List[Pet]] = { + // create path and map variables + val path = (addFmt("/pet/findByTags")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (tags == null) throw new Exception("Missing required parameter 'tags' when calling PetApi->findPetsByTags") + queryParams += "tags" -> tags.toString + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def getPetById(petId: Long)(implicit reader: ClientResponseReader[Pet]): Future[Pet] = { + // create path and map variables + val path = (addFmt("/pet/{petId}") + replaceAll("\\{" + "petId" + "\\}", petId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def updatePet(body: Pet)(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[Pet]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/pet")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling PetApi->updatePet") + + val resFuture = client.submit("PUT", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def updatePetWithForm(petId: Long, + name: Option[String] = None, + status: Option[String] = None + )(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/pet/{petId}") + replaceAll("\\{" + "petId" + "\\}", petId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def uploadFile(petId: Long, + additionalMetadata: Option[String] = None, + file: Option[File] = None + )(implicit reader: ClientResponseReader[ApiResponse]): Future[ApiResponse] = { + // create path and map variables + val path = (addFmt("/pet/{petId}/uploadImage") + replaceAll("\\{" + "petId" + "\\}", petId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + +} diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/StoreApi.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/StoreApi.scala new file mode 100644 index 000000000000..ed574a0eac71 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/StoreApi.scala @@ -0,0 +1,248 @@ +/** + * 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. + * + * OpenAPI spec version: 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 java.text.SimpleDateFormat + +import org.openapitools.client.model.Order +import org.openapitools.client.{ApiInvoker, ApiException} + +import collection.mutable +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart +import com.wordnik.swagger.client._ +import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._ +import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._ + +import java.net.URI +import java.io.File +import java.util.Date +import java.util.TimeZone +import javax.ws.rs.core.MediaType + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.collection.mutable.HashMap +import scala.util.{Failure, Success, Try} + +import org.json4s._ + +class StoreApi( + val defBasePath: String = "http://petstore.swagger.io/v2", + defApiInvoker: ApiInvoker = ApiInvoker +) { + private lazy val dateTimeFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + private val dateFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + implicit val formats = new org.json4s.DefaultFormats { + override def dateFormatter = dateTimeFormatter + } + implicit val stringReader: ClientResponseReader[String] = ClientResponseReaders.StringReader + implicit val unitReader: ClientResponseReader[Unit] = ClientResponseReaders.UnitReader + implicit val jvalueReader: ClientResponseReader[JValue] = ClientResponseReaders.JValueReader + implicit val jsonReader: ClientResponseReader[Nothing] = JsonFormatsReader + implicit val stringWriter: RequestWriter[String] = RequestWriters.StringWriter + implicit val jsonWriter: RequestWriter[Nothing] = JsonFormatsWriter + + var basePath: String = defBasePath + var apiInvoker: ApiInvoker = defApiInvoker + + def addHeader(key: String, value: String): mutable.HashMap[String, String] = { + apiInvoker.defaultHeaders += key -> value + } + + val config: SwaggerConfig = SwaggerConfig.forUrl(new URI(defBasePath)) + val client = new RestClient(config) + val helper = new StoreApiAsyncHelper(client, config) + + /** + * Delete purchase order by ID + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * @param orderId ID of the order that needs to be deleted + * @return void + */ + def deleteOrder(orderId: String) = { + val await = Try(Await.result(deleteOrderAsync(orderId), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Delete purchase order by ID asynchronously + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * @param orderId ID of the order that needs to be deleted + * @return Future(void) + */ + def deleteOrderAsync(orderId: String) = { + helper.deleteOrder(orderId) + } + + /** + * Returns pet inventories by status + * Returns a map of status codes to quantities + * + * @return Map[String, Integer] + */ + def getInventory(): Option[Map[String, Integer]] = { + val await = Try(Await.result(getInventoryAsync(), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Returns pet inventories by status asynchronously + * Returns a map of status codes to quantities + * + * @return Future(Map[String, Integer]) + */ + def getInventoryAsync(): Future[Map[String, Integer]] = { + helper.getInventory() + } + + /** + * Find purchase order by ID + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * + * @param orderId ID of pet that needs to be fetched + * @return Order + */ + def getOrderById(orderId: Long): Option[Order] = { + val await = Try(Await.result(getOrderByIdAsync(orderId), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Find purchase order by ID asynchronously + * For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + * + * @param orderId ID of pet that needs to be fetched + * @return Future(Order) + */ + def getOrderByIdAsync(orderId: Long): Future[Order] = { + helper.getOrderById(orderId) + } + + /** + * Place an order for a pet + * + * + * @param body order placed for purchasing the pet + * @return Order + */ + def placeOrder(body: Order): Option[Order] = { + val await = Try(Await.result(placeOrderAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Place an order for a pet asynchronously + * + * + * @param body order placed for purchasing the pet + * @return Future(Order) + */ + def placeOrderAsync(body: Order): Future[Order] = { + helper.placeOrder(body) + } + +} + +class StoreApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) { + + def deleteOrder(orderId: String)(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/store/order/{orderId}") + replaceAll("\\{" + "orderId" + "\\}", orderId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (orderId == null) throw new Exception("Missing required parameter 'orderId' when calling StoreApi->deleteOrder") + + + val resFuture = client.submit("DELETE", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def getInventory()(implicit reader: ClientResponseReader[Map[String, Integer]]): Future[Map[String, Integer]] = { + // create path and map variables + val path = (addFmt("/store/inventory")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def getOrderById(orderId: Long)(implicit reader: ClientResponseReader[Order]): Future[Order] = { + // create path and map variables + val path = (addFmt("/store/order/{orderId}") + replaceAll("\\{" + "orderId" + "\\}", orderId.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def placeOrder(body: Order)(implicit reader: ClientResponseReader[Order], writer: RequestWriter[Order]): Future[Order] = { + // create path and map variables + val path = (addFmt("/store/order")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling StoreApi->placeOrder") + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + +} diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/UserApi.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/UserApi.scala new file mode 100644 index 000000000000..141e7a18dd8b --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/api/UserApi.scala @@ -0,0 +1,432 @@ +/** + * 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. + * + * OpenAPI spec version: 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 java.text.SimpleDateFormat + +import org.openapitools.client.model.User +import org.openapitools.client.{ApiInvoker, ApiException} + +import collection.mutable +import com.sun.jersey.multipart.FormDataMultiPart +import com.sun.jersey.multipart.file.FileDataBodyPart +import com.wordnik.swagger.client._ +import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._ +import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._ + +import java.net.URI +import java.io.File +import java.util.Date +import java.util.TimeZone +import javax.ws.rs.core.MediaType + +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.collection.mutable.HashMap +import scala.util.{Failure, Success, Try} + +import org.json4s._ + +class UserApi( + val defBasePath: String = "http://petstore.swagger.io/v2", + defApiInvoker: ApiInvoker = ApiInvoker +) { + private lazy val dateTimeFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + private val dateFormatter = { + val formatter = new SimpleDateFormat("yyyy-MM-dd") + formatter.setTimeZone(TimeZone.getTimeZone("UTC")) + formatter + } + implicit val formats = new org.json4s.DefaultFormats { + override def dateFormatter = dateTimeFormatter + } + implicit val stringReader: ClientResponseReader[String] = ClientResponseReaders.StringReader + implicit val unitReader: ClientResponseReader[Unit] = ClientResponseReaders.UnitReader + implicit val jvalueReader: ClientResponseReader[JValue] = ClientResponseReaders.JValueReader + implicit val jsonReader: ClientResponseReader[Nothing] = JsonFormatsReader + implicit val stringWriter: RequestWriter[String] = RequestWriters.StringWriter + implicit val jsonWriter: RequestWriter[Nothing] = JsonFormatsWriter + + var basePath: String = defBasePath + var apiInvoker: ApiInvoker = defApiInvoker + + def addHeader(key: String, value: String): mutable.HashMap[String, String] = { + apiInvoker.defaultHeaders += key -> value + } + + val config: SwaggerConfig = SwaggerConfig.forUrl(new URI(defBasePath)) + val client = new RestClient(config) + val helper = new UserApiAsyncHelper(client, config) + + /** + * Create user + * This can only be done by the logged in user. + * + * @param body Created user object + * @return void + */ + def createUser(body: User) = { + val await = Try(Await.result(createUserAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Create user asynchronously + * This can only be done by the logged in user. + * + * @param body Created user object + * @return Future(void) + */ + def createUserAsync(body: User) = { + helper.createUser(body) + } + + /** + * Creates list of users with given input array + * + * + * @param body List of user object + * @return void + */ + def createUsersWithArrayInput(body: List[User]) = { + val await = Try(Await.result(createUsersWithArrayInputAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Creates list of users with given input array asynchronously + * + * + * @param body List of user object + * @return Future(void) + */ + def createUsersWithArrayInputAsync(body: List[User]) = { + helper.createUsersWithArrayInput(body) + } + + /** + * Creates list of users with given input array + * + * + * @param body List of user object + * @return void + */ + def createUsersWithListInput(body: List[User]) = { + val await = Try(Await.result(createUsersWithListInputAsync(body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Creates list of users with given input array asynchronously + * + * + * @param body List of user object + * @return Future(void) + */ + def createUsersWithListInputAsync(body: List[User]) = { + helper.createUsersWithListInput(body) + } + + /** + * Delete user + * This can only be done by the logged in user. + * + * @param username The name that needs to be deleted + * @return void + */ + def deleteUser(username: String) = { + val await = Try(Await.result(deleteUserAsync(username), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Delete user asynchronously + * This can only be done by the logged in user. + * + * @param username The name that needs to be deleted + * @return Future(void) + */ + def deleteUserAsync(username: String) = { + helper.deleteUser(username) + } + + /** + * Get user by user name + * + * + * @param username The name that needs to be fetched. Use user1 for testing. + * @return User + */ + def getUserByName(username: String): Option[User] = { + val await = Try(Await.result(getUserByNameAsync(username), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Get user by user name asynchronously + * + * + * @param username The name that needs to be fetched. Use user1 for testing. + * @return Future(User) + */ + def getUserByNameAsync(username: String): Future[User] = { + helper.getUserByName(username) + } + + /** + * Logs user into the system + * + * + * @param username The user name for login + * @param password The password for login in clear text + * @return String + */ + def loginUser(username: String, password: String): Option[String] = { + val await = Try(Await.result(loginUserAsync(username, password), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Logs user into the system asynchronously + * + * + * @param username The user name for login + * @param password The password for login in clear text + * @return Future(String) + */ + def loginUserAsync(username: String, password: String): Future[String] = { + helper.loginUser(username, password) + } + + /** + * Logs out current logged in user session + * + * + * @return void + */ + def logoutUser() = { + val await = Try(Await.result(logoutUserAsync(), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Logs out current logged in user session asynchronously + * + * + * @return Future(void) + */ + def logoutUserAsync() = { + helper.logoutUser() + } + + /** + * Updated user + * This can only be done by the logged in user. + * + * @param username name that need to be deleted + * @param body Updated user object + * @return void + */ + def updateUser(username: String, body: User) = { + val await = Try(Await.result(updateUserAsync(username, body), Duration.Inf)) + await match { + case Success(i) => Some(await.get) + case Failure(t) => None + } + } + + /** + * Updated user asynchronously + * This can only be done by the logged in user. + * + * @param username name that need to be deleted + * @param body Updated user object + * @return Future(void) + */ + def updateUserAsync(username: String, body: User) = { + helper.updateUser(username, body) + } + +} + +class UserApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) { + + def createUser(body: User)(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[User]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling UserApi->createUser") + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def createUsersWithArrayInput(body: List[User])(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[List[User]]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user/createWithArray")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling UserApi->createUsersWithArrayInput") + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def createUsersWithListInput(body: List[User])(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[List[User]]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user/createWithList")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (body == null) throw new Exception("Missing required parameter 'body' when calling UserApi->createUsersWithListInput") + + val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def deleteUser(username: String)(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user/{username}") + replaceAll("\\{" + "username" + "\\}", username.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (username == null) throw new Exception("Missing required parameter 'username' when calling UserApi->deleteUser") + + + val resFuture = client.submit("DELETE", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def getUserByName(username: String)(implicit reader: ClientResponseReader[User]): Future[User] = { + // create path and map variables + val path = (addFmt("/user/{username}") + replaceAll("\\{" + "username" + "\\}", username.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (username == null) throw new Exception("Missing required parameter 'username' when calling UserApi->getUserByName") + + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def loginUser(username: String, + password: String)(implicit reader: ClientResponseReader[String]): Future[String] = { + // create path and map variables + val path = (addFmt("/user/login")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (username == null) throw new Exception("Missing required parameter 'username' when calling UserApi->loginUser") + + if (password == null) throw new Exception("Missing required parameter 'password' when calling UserApi->loginUser") + + queryParams += "username" -> username.toString + queryParams += "password" -> password.toString + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def logoutUser()(implicit reader: ClientResponseReader[Unit]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user/logout")) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + + val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "") + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + def updateUser(username: String, + body: User)(implicit reader: ClientResponseReader[Unit], writer: RequestWriter[User]): Future[Unit] = { + // create path and map variables + val path = (addFmt("/user/{username}") + replaceAll("\\{" + "username" + "\\}", username.toString)) + + // query params + val queryParams = new mutable.HashMap[String, String] + val headerParams = new mutable.HashMap[String, String] + + if (username == null) throw new Exception("Missing required parameter 'username' when calling UserApi->updateUser") + + if (body == null) throw new Exception("Missing required parameter 'body' when calling UserApi->updateUser") + + val resFuture = client.submit("PUT", path, queryParams.toMap, headerParams.toMap, writer.write(body)) + resFuture flatMap { resp => + process(reader.read(resp)) + } + } + + +} diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/ApiResponse.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/ApiResponse.scala new file mode 100644 index 000000000000..090cbaddd4b4 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/ApiResponse.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. + * + * OpenAPI spec version: 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 + + +case class ApiResponse ( + code: Option[Integer] = None, + `type`: Option[String] = None, + message: Option[String] = None +) + diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Category.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Category.scala new file mode 100644 index 000000000000..5040e0cb96f1 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Category.scala @@ -0,0 +1,20 @@ +/** + * 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. + * + * OpenAPI spec version: 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 + + +case class Category ( + id: Option[Long] = None, + name: Option[String] = None +) + diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Order.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Order.scala new file mode 100644 index 000000000000..72f09d7a74ee --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Order.scala @@ -0,0 +1,26 @@ +/** + * 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. + * + * OpenAPI spec version: 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.util.Date + +case class Order ( + id: Option[Long] = None, + petId: Option[Long] = None, + quantity: Option[Integer] = None, + shipDate: Option[Date] = None, + // Order Status + status: Option[String] = None, + complete: Option[Boolean] = None +) + diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Pet.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Pet.scala new file mode 100644 index 000000000000..1f060b10c7fb --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Pet.scala @@ -0,0 +1,25 @@ +/** + * 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. + * + * OpenAPI spec version: 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 + + +case class Pet ( + id: Option[Long] = None, + category: Option[Category] = None, + name: String, + photoUrls: List[String], + tags: Option[List[Tag]] = None, + // pet status in the store + status: Option[String] = None +) + diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Tag.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Tag.scala new file mode 100644 index 000000000000..da3cd4acd441 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/Tag.scala @@ -0,0 +1,20 @@ +/** + * 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. + * + * OpenAPI spec version: 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 + + +case class Tag ( + id: Option[Long] = None, + name: Option[String] = None +) + diff --git a/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/User.scala b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/User.scala new file mode 100644 index 000000000000..cd4c1c9b6702 --- /dev/null +++ b/samples/client/petstore/scala-httpclient/bin/org/openapitools/client/model/User.scala @@ -0,0 +1,27 @@ +/** + * 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. + * + * OpenAPI spec version: 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 + + +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[Integer] = None +) + diff --git a/samples/meta-codegen/lib/README.md b/samples/meta-codegen/lib/README.md index 949071334367..d0e89786c074 100644 --- a/samples/meta-codegen/lib/README.md +++ b/samples/meta-codegen/lib/README.md @@ -64,6 +64,9 @@ The `MyclientcodegenGenerator.java` has comments in it--lots of comments. There for reading the code more, though. See how the `MyclientcodegenGenerator` implements `CodegenConfig`. That class has the signature of all values that can be overridden. +You can also step through MyclientcodegenGenerator.java in a debugger. Just debug the JUnit +test in DebugCodegenLauncher. That runs the command line tool and lets you inspect what the code is doing. + For the templates themselves, you have a number of values available to you for generation. You can execute the `java` command from above while passing different debug flags to show the object you have available during client generation: diff --git a/samples/meta-codegen/lib/pom.xml b/samples/meta-codegen/lib/pom.xml index 0a6d0e604670..c431b745323c 100644 --- a/samples/meta-codegen/lib/pom.xml +++ b/samples/meta-codegen/lib/pom.xml @@ -113,6 +113,16 @@ ${openapi-generator-version} provided + + org.openapitools + openapi-generator-cli + ${openapi-generator-version} + + + junit + junit + ${junit-version} + UTF-8 diff --git a/samples/meta-codegen/lib/src/main/java/com/my/company/codegen/MyclientcodegenGenerator.java b/samples/meta-codegen/lib/src/main/java/com/my/company/codegen/MyclientcodegenGenerator.java index fd43a342519c..f194080a4d64 100644 --- a/samples/meta-codegen/lib/src/main/java/com/my/company/codegen/MyclientcodegenGenerator.java +++ b/samples/meta-codegen/lib/src/main/java/com/my/company/codegen/MyclientcodegenGenerator.java @@ -32,6 +32,31 @@ public String getName() { return "myClientCodegen"; } + /** + * Provides an opportunity to inspect and modify operation data before the code is generated. + */ + @SuppressWarnings("unchecked") + @Override + public Map postProcessOperationsWithModels(Map objs, List allModels) { + + // to try debugging your code generator: + // set a break point on the next line. + // then debug the JUnit test called LaunchGeneratorInDebugger + + Map results = super.postProcessOperationsWithModels(objs, allModels); + + Map ops = (Map)results.get("operations"); + ArrayList opList = (ArrayList)ops.get("operation"); + + // iterate over the operation and perhaps modify something + for(CodegenOperation co : opList){ + // example: + // co.httpMethod = co.httpMethod.toLowerCase(); + } + + return results; + } + /** * Returns human-friendly help for the generator. Provide the consumer with help * tips, parameters here diff --git a/samples/meta-codegen/lib/src/test/java/org/openapitools/codegen/debug/DebugCodegenLauncher.java b/samples/meta-codegen/lib/src/test/java/org/openapitools/codegen/debug/DebugCodegenLauncher.java new file mode 100644 index 000000000000..46f2e3e314e7 --- /dev/null +++ b/samples/meta-codegen/lib/src/test/java/org/openapitools/codegen/debug/DebugCodegenLauncher.java @@ -0,0 +1,40 @@ +package org.openapitools.codegen.debug; + +import org.junit.Test; +import org.openapitools.codegen.OpenAPIGenerator; + +/*** + * This test allows you to easily launch your code generation software under a debugger. + * Then run this test under debug mode. You will be able to step through your java code + * and then see the results in the out directory. + * + * To experiment with debugging your code generator: + * 1) Set a break point in MyclientcodegenGenerator.java in the postProcessOperationsWithModels() method. + * 2) To launch this test in Eclipse: right-click | Debug As | JUnit Test + * + */ +public class DebugCodegenLauncher +{ + @Test + public void launchCodeGeneratorInDebugMode() + { + // use this test to launch you code generator in the debugger. + // this allows you to easily set break points in MyclientcodegenGenerator. + String commandLineParams = + "generate "+ + "-i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml "+ // sample swagger + "-t ./src/main/resources/myClientCodegen "+ // template directory + "-o out/myClientCodegen "+ // output directory + "-g myClientCodegen "; // use this codegen library + + try{ + OpenAPIGenerator.main( commandLineParams.split(" ") ); + } + catch(Exception ex) { + System.err.println(ex.toString()); + } + catch(Error er) { + System.err.println(er.toString()); + } + } +} \ No newline at end of file