Kotlin client: add volley library support (#10253)

* Add basic jvm-volley folder to enable it as a library

* Add JVM_VOLLEY to the KotlinClientCodegen as a library option (using Retrofit2 processing for now)

* Temporary checkin of generated code and kotlinfied version for use in new template

* Added Kotlin-ified api invoker and request objects, update Kotlin client codgen for volley

* Add Android specific build.gradle mustache file to jvm-volley library

* Hardcode SDK version and build tools version in build.gradle template, add extra repository for Android Gradle build tools

* Add Android manifest to generated code

* Add Kotlin dependencies and plugins to build gradle template

* WIP: Create basic API templating for jvm-volley

* Add ApiException and parameter validation, create path variable using ApiInvoker

* Build queryParams and headerParams

* Add VolleyRequest template

* WIP: Injecting context and default API invoker into APIs (non compiling)

* Add DefaultInvoker stub and update API to inject context

* Add request queue generation to the DefaultInvoker

* Fix up compile errors in the invoker

* Cleanup unrequired templates

* Update templates

* Add constructor overloads to inject stack or network into request queue

* Fix compile errors with request queue generation

* Fix compile errors

* Al'll fix it for you.....

* WIP compile fixes

* More compile fixes

* Generate to java directory and kotlin-ify auth code

* More syntax fixes in templates

* Almost left it in a working state, fixing that .... now...

* Switch builder method based on model existence constraints - body and response

* Add coroutine logic to APIs and pass through listeners to the requests, various other fixes.

* Use reflection and type tokens to work around clazz issues on generics

* Add POST, PATCH and PUT to RequestFactory

* More templating magic

* Fix Steve, the human compiler's errors again !

* Add CLI option for generating room models

* Configure the room model package

* Add initial room model templating and generation

* Add room model generation implementation

* Implement toRoom function on models to convert model to room model

* Bug fixes, transformers to and from room models

* Add query parameters to URL generation

* Fix issues with gson type conversion, add type adapters to gson instance

* Fix issues with older API versions and Java8 libraries,

* Add request factory interface

* API template tidy up

* Update IRequestFactory to include companion object, minor tidy ups

* Remove @Keep annotations from room templates

* Rename toRoomModel and toApiModel functions

* Add empty companion object to generated room model

* Add ITransformStorage interface to allow polymorphic transforms to room models

* Add content type into GsonRequest

* Move gson serialization of request body into GsonRequest

* Update request factory to take header factories

* Remove the generated comparision code

* Move the generateRoomModels switch into the KotlinClientCodegen class

* Move room model generation out of default generator

* Updates for auth

* Finalise removal of kotlin elements from default generator

* Hoist room model logic out of abstractKotlin into kotlin client codegen

* Revert AbstractKotlinCodegen

* Revert Codegen constants to remove base generator changes out of our new library

* Revert data class template changes, add data class body check to Kotlin Client codegen

* Add sample generation yaml file for jvm-volley library

* Update JVM-Volley readme for generateRoomModels flag

* Remove unused template files, get auth compiling but non functional, clean build of warnings

* Generate sample generated code

* Add not implemented method for oauth

* Add unit test for KotlinClientCodegen generateRoomModel flag

* Remove accidental hard coding of src/main/java source folder

* Push changed generated sample files

* Move and rename IStorable inside the volley library

* Inject retry policy into API definition, re-run sample and doc scripts

* Add generic post processors

* Update samples after generator changes

* Fix some compile errors with the pet store sample

* Fix duplicate auth companion object and import generation

* Reinstate query and form parameter code generation

* Add check for unsupported serialization libraries

* Fix broken unit tests

* Regenerate samples

* AN-233 Update request factory to allow custom gsonadapters

* update `GsonRequest.mustache` and `RequestFactoy.mustache` to use `Map<Type, Any>` instead of `Map<Type, Object>` to better fit kotlin conventions

* Update readme with better examples and design notes

* Update readme with info about gson serializers and adapters for polymorphic types

* Updated samples

* Merge from upstream

* Address review comments

* Update samples

* Samples

* Update docs

* Remove DateAdapter generated file, template and it's inclusion as a supporting file in favour of localDateTime

* Review comment cleanup for initial PR #10253 - cleaner auth key in parameter string handling

* Review comment - add a kotlin version parameter to the build scripts

* Updated samples

* Missing changes from build.mustache

* Regenerate samples for build.gradle changes

* Merge from master and generate samples

* Remove serializer as a supporting file from jvm-volley - it's serialisation is not a singleton and configured differently via gson request and dependency injection

* Remove singleton serializer from jvm-volley generation as it's not used

Co-authored-by: Alister Shipman <alister.shipman@greater.com.au>
Co-authored-by: Steve Telford <steven.telford@greater.com.au>
Co-authored-by: Leigh Cooper <leigh.cooper@greater.com.au>
Co-authored-by: Michael Hewett <y2trooper@gmail.com>
This commit is contained in:
alisters 2021-12-20 17:59:11 +11:00 committed by GitHub
parent b72eba90cd
commit 0de482da2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 5591 additions and 6 deletions

View File

@ -0,0 +1,9 @@
generatorName: kotlin
outputDir: samples/client/petstore/kotlin-jvm-volley
library: jvm-volley
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-client
additionalProperties:
artifactId: kotlin-petstore-jvm-volley
generateRoomModels: "true"
serializationLibrary: "gson"

View File

@ -13,8 +13,9 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|collectionType|Option. Collection type to use|<dl><dt>**array**</dt><dd>kotlin.Array</dd><dt>**list**</dt><dd>kotlin.collections.List</dd></dl>|list|
|dateLibrary|Option. Date library to use|<dl><dt>**threetenbp-localdatetime**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, for legacy app only)</dd><dt>**string**</dt><dd>String</dd><dt>**java8-localdatetime**</dt><dd>Java 8 native JSR310 (jvm only, for legacy app only)</dd><dt>**java8**</dt><dd>Java 8 native JSR310 (jvm only, preferred for jdk 1.8+)</dd><dt>**threetenbp**</dt><dd>Threetenbp - Backport of JSR310 (jvm only, preferred for jdk &lt; 1.8)</dd></dl>|java8|
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|generateRoomModels|Generate Android Room database models in addition to API models (JVM Volley library only)| |false|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|library|Library template (sub-template) to use|<dl><dt>**jvm-okhttp4**</dt><dd>[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-okhttp3**</dt><dd>Platform: Java Virtual Machine. HTTP client: OkHttp 3.12.4 (Android 2.3+ and Java 7+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-retrofit2**</dt><dd>Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.</dd><dt>**multiplatform**</dt><dd>Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.0. JSON processing: Kotlinx Serialization: 1.2.1.</dd></dl>|jvm-okhttp4|
|library|Library template (sub-template) to use|<dl><dt>**jvm-okhttp4**</dt><dd>[DEFAULT] Platform: Java Virtual Machine. HTTP client: OkHttp 4.2.0 (Android 5.0+ and Java 8+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-okhttp3**</dt><dd>Platform: Java Virtual Machine. HTTP client: OkHttp 3.12.4 (Android 2.3+ and Java 7+). JSON processing: Moshi 1.8.0.</dd><dt>**jvm-retrofit2**</dt><dd>Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.</dd><dt>**multiplatform**</dt><dd>Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.0. JSON processing: Kotlinx Serialization: 1.2.1.</dd><dt>**jvm-volley**</dt><dd>Platform: JVM for Android. HTTP client: Volley 1.2.1. JSON processing: gson 2.8.9</dd></dl>|jvm-okhttp4|
|modelMutable|Create mutable models| |false|
|moshiCodeGen|Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info.| |false|
|omitGradlePluginVersions|Whether to declare Gradle plugin versions in build files.| |false|

View File

@ -57,12 +57,15 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
protected static final String JVM_OKHTTP3 = "jvm-okhttp3";
protected static final String JVM_RETROFIT2 = "jvm-retrofit2";
protected static final String MULTIPLATFORM = "multiplatform";
protected static final String JVM_VOLLEY = "jvm-volley";
public static final String USE_RX_JAVA = "useRxJava";
public static final String USE_RX_JAVA2 = "useRxJava2";
public static final String USE_RX_JAVA3 = "useRxJava3";
public static final String USE_COROUTINES = "useCoroutines";
public static final String DO_NOT_USE_RX_AND_COROUTINES = "doNotUseRxAndCoroutines";
public static final String GENERATE_ROOM_MODELS = "generateRoomModels";
public static final String ROOM_MODEL_PACKAGE = "roomModelPackage";
public static final String OMIT_GRADLE_PLUGIN_VERSIONS = "omitGradlePluginVersions";
public static final String DATE_LIBRARY = "dateLibrary";
@ -85,6 +88,9 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
// backwards compatibility for openapi configs that specify neither rx1 nor rx2
// (mustache does not allow for boolean operators so we need this extra field)
protected boolean doNotUseRxAndCoroutines = true;
protected boolean generateRoomModels = false;
protected String roomModelPackage = "";
protected String authFolder;
@ -167,6 +173,9 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
outputFolder = "generated-code" + File.separator + "kotlin-client";
modelTemplateFiles.put("model.mustache", ".kt");
if (generateRoomModels) {
modelTemplateFiles.put("model_room.mustache", ".kt");
}
apiTemplateFiles.put("api.mustache", ".kt");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
@ -197,6 +206,7 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
supportedLibraries.put(JVM_OKHTTP3, "Platform: Java Virtual Machine. HTTP client: OkHttp 3.12.4 (Android 2.3+ and Java 7+). JSON processing: Moshi 1.8.0.");
supportedLibraries.put(JVM_RETROFIT2, "Platform: Java Virtual Machine. HTTP client: Retrofit 2.6.2.");
supportedLibraries.put(MULTIPLATFORM, "Platform: Kotlin multiplatform. HTTP client: Ktor 1.6.0. JSON processing: Kotlinx Serialization: 1.2.1.");
supportedLibraries.put(JVM_VOLLEY, "Platform: JVM for Android. HTTP client: Volley 1.2.1. JSON processing: gson 2.8.9");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "Library template (sub-template) to use");
libraryOption.setEnum(supportedLibraries);
@ -220,6 +230,8 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
cliOptions.add(CliOption.newBoolean(MOSHI_CODE_GEN, "Whether to enable codegen with the Moshi library. Refer to the [official Moshi doc](https://github.com/square/moshi#codegen) for more info."));
cliOptions.add(CliOption.newBoolean(GENERATE_ROOM_MODELS, "Generate Android Room database models in addition to API models (JVM Volley library only)", false));
cliOptions.add(CliOption.newBoolean(SUPPORT_ANDROID_API_LEVEL_25_AND_BELLOW, "[WARNING] This flag will generate code that has a known security vulnerability. It uses `kotlin.io.createTempFile` instead of `java.nio.file.Files.createTempFile` in oder to support Android API level 25 and bellow. For more info, please check the following links https://github.com/OpenAPITools/openapi-generator/security/advisories/GHSA-23x4-m842-fmwf, https://github.com/OpenAPITools/openapi-generator/pull/9284"));
}
@ -235,6 +247,12 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
return "Generates a Kotlin client.";
}
public boolean getGenerateRoomModels() { return generateRoomModels; }
public void setGenerateRoomModels(Boolean generateRoomModels) {
this.generateRoomModels = generateRoomModels;
}
public void setUseRxJava(boolean useRxJava) {
if (useRxJava) {
this.useRxJava2 = false;
@ -298,14 +316,45 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
this.collectionType = collectionType;
}
public void setRoomModelPackage(String roomModelPackage) {
this.roomModelPackage = roomModelPackage;
}
@Override
public String modelFilename(String templateName, String modelName) {
String suffix = modelTemplateFiles().get(templateName);
// If this was a proper template method, i wouldn't have to make myself throw up by doing this....
if (getGenerateRoomModels() && suffix.startsWith("RoomModel")) {
return roomModelFileFolder() + File.separator + toModelFilename(modelName) + suffix;
} else {
return modelFileFolder() + File.separator + toModelFilename(modelName) + suffix;
}
}
public String roomModelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + roomModelPackage.replace('.', File.separatorChar);
}
@Override
public void processOpts() {
super.processOpts();
if (MULTIPLATFORM.equals(getLibrary())) {
sourceFolder = "src/commonMain/kotlin";
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
} else {
// Set the value to defaults if we haven't overridden
if (MULTIPLATFORM.equals(getLibrary())) {
setSourceFolder("src/commonMain/kotlin");
}
else if (JVM_VOLLEY.equals(getLibrary())){
// Android plugin wants it's source in java
setSourceFolder("src/main/java");
}
else {
setSourceFolder(super.sourceFolder);
}
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder);
}
super.processOpts();
boolean hasRx = additionalProperties.containsKey(USE_RX_JAVA);
boolean hasRx2 = additionalProperties.containsKey(USE_RX_JAVA2);
@ -348,6 +397,12 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", "/");
authFolder = (sourceFolder + File.separator + packageName + File.separator + "auth").replace(".", "/");
// request destination folder
final String requestFolder = (sourceFolder + File.separator + packageName + File.separator + "request").replace(".", "/");
// auth destination folder
final String authFolder = (sourceFolder + File.separator + packageName + File.separator + "auth").replace(".", "/");
// additional properties
if (additionalProperties.containsKey(DATE_LIBRARY)) {
setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString());
@ -364,6 +419,9 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
case JVM_OKHTTP4:
processJVMOkHttpLibrary(infrastructureFolder);
break;
case JVM_VOLLEY:
processJVMVolleyLibrary(infrastructureFolder, requestFolder, authFolder);
break;
case JVM_RETROFIT2:
processJVMRetrofit2Library(infrastructureFolder);
break;
@ -477,6 +535,47 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
addSupportingSerializerAdapters(infrastructureFolder);
}
private void processJVMVolleyLibrary(String infrastructureFolder, String requestFolder, String authFolder) {
additionalProperties.put(JVM, true);
additionalProperties.put(JVM_VOLLEY, true);
if (additionalProperties.containsKey(GENERATE_ROOM_MODELS)) {
this.setGenerateRoomModels(convertPropertyToBooleanAndWriteBack(GENERATE_ROOM_MODELS));
// Hide this option behind a property getter and setter in case we need to check it elsewhere
if (getGenerateRoomModels()) {
modelTemplateFiles.put("model_room.mustache", "RoomModel.kt");
supportingFiles.add(new SupportingFile("infrastructure/ITransformForStorage.mustache", infrastructureFolder, "ITransformForStorage.kt"));
}
} else {
additionalProperties.put(GENERATE_ROOM_MODELS, generateRoomModels);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
if (!additionalProperties.containsKey(ROOM_MODEL_PACKAGE))
this.setRoomModelPackage(packageName + ".models.room");
else
this.setRoomModelPackage(additionalProperties.get(ROOM_MODEL_PACKAGE).toString());
}
additionalProperties.put(ROOM_MODEL_PACKAGE, roomModelPackage);
supportingFiles.add(new SupportingFile("infrastructure/CollectionFormats.kt.mustache", infrastructureFolder, "CollectionFormats.kt"));
// We have auth related partial files, so they can be overridden, but don't generate them explicitly
supportingFiles.add(new SupportingFile("request/GsonRequest.mustache", requestFolder, "GsonRequest.kt"));
supportingFiles.add(new SupportingFile("request/IRequestFactory.mustache", requestFolder, "IRequestFactory.kt"));
supportingFiles.add(new SupportingFile("request/RequestFactory.mustache", requestFolder, "RequestFactory.kt"));
supportingFiles.add(new SupportingFile("infrastructure/CollectionFormats.kt.mustache", infrastructureFolder, "CollectionFormats.kt"));
if (getSerializationLibrary() != SERIALIZATION_LIBRARY_TYPE.gson) {
throw new RuntimeException("This library currently only supports gson serialization. Try adding '--additional-properties serializationLibrary=gson' to your command.");
}
addSupportingSerializerAdapters(infrastructureFolder);
supportingFiles.remove(new SupportingFile("jvm-common/infrastructure/Serializer.kt.mustache", infrastructureFolder, "Serializer.kt"));
}
private void addSupportingSerializerAdapters(final String infrastructureFolder) {
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/Serializer.kt.mustache", infrastructureFolder, "Serializer.kt"));
supportingFiles.add(new SupportingFile("jvm-common/infrastructure/ByteArrayAdapter.kt.mustache", infrastructureFolder, "ByteArrayAdapter.kt"));
@ -605,6 +704,11 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
if (getLibrary().equals(MULTIPLATFORM)) {
supportingFiles.add(new SupportingFile("build.gradle.kts.mustache", "", "build.gradle.kts"));
supportingFiles.add(new SupportingFile("settings.gradle.kts.mustache", "", "settings.gradle.kts"));
} else if (getLibrary().equals(JVM_VOLLEY)) {
supportingFiles.add(new SupportingFile("build.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("manifest.mustache", "", "src/main/AndroidManifest.xml"));
} else {
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
@ -625,6 +729,9 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
for (Object model : models) {
@SuppressWarnings("unchecked") Map<String, Object> mo = (Map<String, Object>) model;
CodegenModel cm = (CodegenModel) mo.get("model");
if (getGenerateRoomModels()) {
cm.vendorExtensions.put("x-has-data-class-body", true);
}
// escape the variable base name for use as a string literal
List<CodegenProperty> vars = Stream.of(

View File

@ -35,6 +35,10 @@ import kotlinx.serialization.encoding.*
{{#serializableModel}}
import java.io.Serializable
{{/serializableModel}}
{{#generateRoomModels}}
import {{roomModelPackage}}.{{classname}}RoomModel
import {{packageName}}.infrastructure.ITransformForStorage
{{/generateRoomModels}}
/**
* {{{description}}}
@ -56,8 +60,16 @@ import java.io.Serializable
{{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}}
{{/allVars}}
){{/discriminator}}{{#parent}}{{^serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{^serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{^parcelizeModels}} : Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{#parcelizeModels}} : Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#vendorExtensions.x-has-data-class-body}} {
){{/discriminator}}{{#parent}}{{^serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{^parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{^serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#parent}}{{#serializableModel}}{{#parcelizeModels}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}, Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{^parcelizeModels}} : Serializable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{^parent}}{{#serializableModel}}{{#parcelizeModels}} : Serializable, Parcelable{{/parcelizeModels}}{{/serializableModel}}{{/parent}}{{#generateRoomModels}}{{#parent}}, {{/parent}}{{^discriminator}}{{^parent}}:{{/parent}} ITransformForStorage<{{classname}}RoomModel>{{/discriminator}}{{/generateRoomModels}}{{#vendorExtensions.x-has-data-class-body}} {
{{/vendorExtensions.x-has-data-class-body}}
{{#generateRoomModels}}
companion object { }
{{^discriminator}}override fun toRoomModel(): {{classname}}RoomModel =
{{classname}}RoomModel(roomTableId = 0,
{{#allVars}}{{#items.isPrimitiveType}}{{#isArray}}{{#isList}}{{name}} = this.{{name}},{{/isList}}{{/isArray}}{{/items.isPrimitiveType}}{{^isEnum}}{{^isArray}}{{name}} = this.{{name}},{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{name}} = this.{{name}},{{/isArray}}{{/isEnum}}
{{/allVars}}
){{/discriminator}}
{{/generateRoomModels}}
{{#serializableModel}}
{{#nonPublicApi}}internal {{/nonPublicApi}}companion object {
private const val serialVersionUID: Long = 123

View File

@ -0,0 +1,232 @@
# {{packageName}} - Kotlin client library for {{appName}}
A kotlin client for Android using the currently recommended http client, Volley. See https://developer.android.com/training/volley
- Currently sends GsonRequests
- Currently only supports Gson as a serializer - will throw an exception if a different serializer is chosen
- Defaults the source location to src/main/java as per standard Android builds
## Design
Volley is a queue/request based layer on top of http url stack specific to Android. Android favours dependency injection and
a layered architecture, and IO performed off the main thread to maintain UI responsiveness, with a preferred technique of
kotlin co-routines. The code gen library reflects these factors.
- Api calls use co-routines, and execute them using volley callbacks to avoid tying up a thread.
- Facilitate dependency injection, with default implementations available.
- Generate a requestFactory that can be overridden
- Allow the passing of the RequestFactory per tag (api client) or per operation (an extra parameter is created on operations with non-global security), with per operation auth overriding global security.
- DI scoping of the Request Factory and pre-generated auth header factories allow for thread safe and secure setting of credentials.
- Lazy header factories allow for refreshing tokens etc
- Factoring of header factories to the Request Factory allow ambient provision of credentials. Code gen library is credential storage agnostic.
- Header factories allow the merging of generated headers from open api spec with dynamically added headers
- Injection of http url stack to allow custom http stacks. Default implementation is best practice singleton
- Data classes used for serialisation to reflect volley's preference - an immutable request that once queued can't be tampered with.
- Reuse model class and other jvm common infrastructure
- Optional generation of room database models, and transform methods to these from open api models
- Room and api models can be extended with additional extension properties.
## Future improvements
- Option to generate image requests on certain conditionals e.g content-type gif etc
- Support for kotlin serialization.
- Multi part form parameters and support for file inputs
## Usage
Hilt Dependency injection example - with default values for parameters overridden.
```
@Provides
internal fun provideSomeApi(
context: Context,
restService: IRestService,
configurationService: IConfigurationService,
sessionService: ISessionService
): SomeApi {
return SomeApi(
context = context,
requestQueue = restService.getRequestQueue(),
requestFactory = RequestFactory(listOf(createSessionHeaderFactory(sessionService), createTraceHeaderFactory()),
postProcessors = listOf(retryPolicySetter)),
basePath = configurationService.getBaseUrl()
)
}
```
Here is the constructor so you can see the defaults
```class SomeApi (
val context: Context,
val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
val requestFactory: IRequestFactory = RequestFactory(),
val basePath: String = "https://yourbasepath.from_input_parameter.com/api",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
```
### Overriding defaults
The above constructor for each api allows the following to be customized
- A custom context, so either a singleton request queue or different scope can be created - see
https://developer.android.com/training/volley/requestqueue#singleton
- An overrideable request queue - which in turn can have a custom http url stack passed to it
- An overrideable request factory constructor call, or a request factory that can be overridden by a custom template, with
custom header factory, request post processors and custom gson adapters injected.
#### Overriding request generation
Request generation can be overridden by
- Overriding the entire request factory template
- Supplying custom header factories - methods that take any possible parameters but return a map of headers
- Supplying custom request post processors - methods that take and return the request object
Header factory examples can be found in the auth section, as these are implemented as header factories. eg
```
val basicAuthHeaderFactoryBuilder = { username: String?, password: String? ->
{ mapOf("Authorization" to "Basic " + Base64.encodeToString("${username ?: ""}:${password ?: ""}".toByteArray(), Base64.DEFAULT))}
}
```
In this case it's a lambda function (a factory method) that takes an username and password, and returns a map of headers. Other
generated code will supply the username and password. In this case it results in a map of just one key/value pair, but
it could be multiple. The important part is it's returning a map - and that the surrounding code
will can bind the inputs to it at some point.
Here is a different example that supplies tracing header values
```
/**
* Create a lambda of tracing headers to be injected into an API's [RequestFactory].
*/
private fun createTraceHeaderFactory(): () -> Map<String, String> = {
mapOf(
HttpHeaderType.b3_traceId.rawValue to UUIDExtensions.asTraceId(UUID.randomUUID()),
HttpHeaderType.b3_spanId.rawValue to UUIDExtensions.asSpanId(UUID.randomUUID()),
HttpHeaderType.b3_sampled.rawValue to "1"
)
}
```
Finally a post processor example
```
/**
* Configure a [DefaultRetryPolicy] to be injected into the [RequestFactory] with a maximum number of retries of zero.
*/
private val retryPolicySetter = { request: Request<*> ->
Unit.apply {
request.setRetryPolicy(
DefaultRetryPolicy(
RestService.DEFAULT_TIMEOUT_MS,
0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
)
}
}
```
### Serialization
#### Gson and Polymorphic types
The GsonRequest object can be passed custom type adapters
```
class GsonRequest<T>(
method: Int,
url: String,
private val body: Any?,
private val headers: Map<String, String>?,
private val params: MutableMap<String, String>?,
private val contentTypeForBody: String?,
private val encodingForParams: String?,
private val gsonAdapters: Map<Type, Object>?,
private val type: Type,
private val listener: Response.Listener<T>,
errorListener: Response.ErrorListener
) : Request<T>(method, url, errorListener) {
val gsonBuilder: GsonBuilder = GsonBuilder()
.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
.registerTypeAdapter(LocalDateTime::class.java, LocalDateTimeAdapter())
.registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
.registerTypeAdapter(ByteArray::class.java, ByteArrayAdapter())
```
## Requires
{{#jvm}}
* Kotlin 1.4.30
* Gradle 6.8.3
{{/jvm}}
{{#multiplatform}}
* Kotlin 1.5.10
{{/multiplatform}}
## Build
{{#jvm}}
First, create the gradle wrapper script:
```
gradle wrapper
```
Then, run:
{{/jvm}}
```
./gradlew check assemble
```
This runs all tests and packages the library.
{{#generateApiDocs}}
<a name="documentation-for-api-endpoints"></a>
## Documentation for API Endpoints
All URIs are relative to *{{{basePath}}}*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
{{/generateApiDocs}}
{{#generateModelDocs}}
<a name="documentation-for-models"></a>
## Documentation for Models
{{#modelPackage}}
{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
{{/model}}{{/models}}
{{/modelPackage}}
{{^modelPackage}}
No model defined in this package
{{/modelPackage}}
{{/generateModelDocs}}
<a name="documentation-for-authorization"></a>{{! TODO: optional documentation for authorization? }}
## Documentation for Authorization
{{^authMethods}}
All endpoints do not require authorization.
{{/authMethods}}
{{#authMethods}}
{{#last}}
Authentication schemes defined for the API:
{{/last}}
{{/authMethods}}
{{#authMethods}}
<a name="{{name}}"></a>
### {{name}}
{{#isApiKey}}- **Type**: API key
- **API key parameter name**: {{keyParamName}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasic}}- **Type**: HTTP basic authentication
{{/isBasic}}
{{#isOAuth}}- **Type**: OAuth
- **Flow**: {{flow}}
- **Authorization URL**: {{authorizationUrl}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}
{{#scopes}} - {{scope}}: {{description}}
{{/scopes}}
{{/isOAuth}}
{{/authMethods}}

View File

@ -0,0 +1,129 @@
package {{apiPackage}}
import android.content.Context
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.BaseHttpStack
import com.android.volley.toolbox.Volley
import java.util.*;
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import com.google.gson.reflect.TypeToken
import {{packageName}}.request.IRequestFactory
import {{packageName}}.request.RequestFactory
import {{packageName}}.infrastructure.CollectionFormats.*
{{#imports}}import {{import}}
{{/imports}}
{{#operations}}
/*
* If you wish to use a custom http stack with your client you
* can pass that to the request queue like:
* Volley.newRequestQueue(context.applicationContext, myCustomHttpStack)
*/
class {{classname}} (
private val context: Context,
private val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
private val requestFactory: IRequestFactory = RequestFactory(),
private val basePath: String = "{{{basePath}}}",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}} * @param {{paramName}} {{description}}
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/
{{#isDeprecated}}
@Deprecated("This api was deprecated")
{{/isDeprecated}}
suspend fun {{operationId}}({{^allParams}}){{/allParams}}{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{#-last}}{{#operationAuthMethod}}, opAuthHeaderFactory = () -> map<String, String>{{/operationAuthMethod}}){{/-last}}{{/allParams}}: {{#returnType}}{{{returnType}}}?{{/returnType}}{{^returnType}}Unit{{/returnType}} {
{{#bodyParam}}
val body: Any? = {{paramName}}
{{/bodyParam}}
{{^bodyParam}}
val body: Any? = null
{{/bodyParam}}
{{#allParams}}
{{#required}}
// verify the required parameter '{{paramName}}' is set
// This is probably taken care of by non-null types anyway
requireNotNull({{paramName}})
{{/required}}
{{/allParams}}
val contentTypes : Array<String> = arrayOf({{#consumes}}"{{{mediaType}}}"{{^-last}},{{/-last}}{{/consumes}})
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "{{{path}}}"{{#pathParams}}.replace("{" + "{{baseName}}" + "}", IRequestFactory.escapeString({{{paramName}}}.toString())){{/pathParams}};
// form params
val formParams = mapOf<String, String>(
{{#formParams}}
"{{baseName}}" to IRequestFactory.parameterToString({{paramName}}),
{{/formParams}}
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
{{#queryParams}}
"{{baseName}}" to IRequestFactory.parameterToString({{paramName}}),
{{/queryParams}}
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
{{#headerParams}}
"{{baseName}}" to IRequestFactory.parameterToString({{paramName}}),
{{/headerParams}}
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}> = requestFactory.build(
Request.Method.{{httpMethod}},
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
{{/operation}}
}
{{/operations}}

View File

@ -0,0 +1,83 @@
# {{classname}}{{#description}}
{{description}}{{/description}}
All URIs are relative to *{{basePath}}*
Method | HTTP request | Description
------------- | ------------- | -------------
{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
{{/operation}}{{/operations}}
{{#operations}}
{{#operation}}
{{summary}}{{#notes}}
{{notes}}{{/notes}}
### Example
```kotlin
// Import classes:
//import {{{packageName}}}.*
//import {{{packageName}}}.infrastructure.*
//import {{{modelPackage}}}.*
val apiClient = ApiClient()
{{#authMethods}}
{{#isBasic}}
{{#isBasicBasic}}
apiClient.setCredentials("USERNAME", "PASSWORD")
{{/isBasicBasic}}
{{#isBasicBearer}}
apiClient.setBearerToken("TOKEN")
{{/isBasicBearer}}
{{/isBasic}}
{{/authMethods}}
val webService = apiClient.createWebservice({{{classname}}}::class.java)
{{#allParams}}
val {{{paramName}}} : {{{dataType}}} = {{{example}}} // {{{dataType}}} | {{{description}}}
{{/allParams}}
{{#useCoroutines}}
launch(Dispatchers.IO) {
{{/useCoroutines}}
{{#useCoroutines}} {{/useCoroutines}}{{#returnType}}val result : {{{returnType}}}{{#nullableReturnType}}?{{/nullableReturnType}} = {{/returnType}}webService.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}})
{{#useCoroutines}}
}
{{/useCoroutines}}
```
### Parameters
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}
{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#generateModelDocs}}[**{{dataType}}**]({{baseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{dataType}}**{{/generateModelDocs}}{{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}}
{{/allParams}}
### Return type
{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#generateModelDocs}}[**{{returnType}}**]({{returnBaseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{returnType}}**{{/generateModelDocs}}{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}}
### Authorization
{{^authMethods}}No authorization required{{/authMethods}}
{{#authMethods}}
{{#isBasic}}
{{#isBasicBasic}}
Configure {{name}}:
ApiClient().setCredentials("USERNAME", "PASSWORD")
{{/isBasicBasic}}
{{#isBasicBearer}}
Configure {{name}}:
ApiClient().setBearerToken("TOKEN")
{{/isBasicBearer}}
{{/isBasic}}
{{/authMethods}}
### HTTP request headers
- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}}
- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}}
{{/operation}}
{{/operations}}

View File

@ -0,0 +1,16 @@
// Api Key auth supports query header and cookie.
// Query is supported in the path generation only with a hardcoded value.
// TODO: Not sure about cookie auth form
// If implementing api key in query parameter use the ^isKeyInHeader property
val apiKeyAuthHeaderFactoryBuilder = {
paramName: String, apiKeyPrefix: String?, apiKey: String? -> {
mapOf(paramName to
if (apiKeyPrefix != null) {
"$apiKeyPrefix $apiKey"
} else {
apiKey!!
}
)
}
}

View File

@ -0,0 +1,15 @@
companion object Authentication {
// Where a header factory requires parameters a client will need to bind these
// TODO Generate appropriate header factories based on settings
{{#authMethods}}
{{#isApiKey}}
{{>auth/apikeyauth}}
{{/isApiKey}}
{{#isBasic}}
{{>auth/httpbasicauth}}
{{/isBasic}}
{{#isOAuth}}
// TODO: Oauth not implemented yet - comment out below as OAuth does not exist
{{/isOAuth}}
{{/authMethods}}
}

View File

@ -0,0 +1,3 @@
val basicAuthHeaderFactoryBuilder = { username: String?, password: String? ->
{ mapOf("Authorization" to "Basic " + Base64.encodeToString("${username ?: ""}:${password ?: ""}".toByteArray(), Base64.DEFAULT))}
}

View File

@ -0,0 +1,5 @@
val basicAuthHeaderFactoryBuilder = { username: String?, password: String? ->
{
throw NotImplementedError("OAuth security scheme header factory not impemented yet - see open api generator auth/oauth.mustache")
mapOf("" to "")}
}

View File

@ -0,0 +1 @@
{{#isBodyParam}}{{{paramName}}}: {{{dataType}}}{{^required}}? = null{{/required}}{{/isBodyParam}}

View File

@ -0,0 +1,129 @@
{{#useAndroidMavenGradlePlugin}}
group = '{{groupId}}'
project.version = '{{artifactVersion}}'
{{/useAndroidMavenGradlePlugin}}
buildscript {
ext.kotlin_version = '1.5.10'
ext.swagger_annotations_version = "1.6.2"
ext.gson_version = "2.8.6"
ext.volley_version = "1.2.0"
ext.junit_version = "4.13.2"
ext.robolectric_version = "4.5.1"
ext.concurrent_unit_version = "0.4.6"
repositories {
mavenLocal()
google()
maven {
url 'https://dl.google.com/dl/android/maven2'
}
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:4.0.2'
{{#useAndroidMavenGradlePlugin}}
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
{{/useAndroidMavenGradlePlugin}}
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
{{#useAndroidMavenGradlePlugin}}
apply plugin: 'com.github.dcendents.android-maven'
{{/useAndroidMavenGradlePlugin}}
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
}
compileOptions {
coreLibraryDesugaringEnabled true
{{#supportJava6}}
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
{{/supportJava6}}
{{^supportJava6}}
{{#java8}}
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
{{/java8}}
{{^java8}}
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
{{/java8}}
{{/supportJava6}}
}
lintOptions {
abortOnError false
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.all { output ->
if (outputFile != null && outputFileName.endsWith('.aar')) {
outputFileName = "${archivesBaseName}-${version}.aar"
}
}
}
testOptions {
unitTests.returnDefaultValues = true
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
implementation "com.google.code.gson:gson:$gson_version"
implementation "com.android.volley:volley:${volley_version}"
testImplementation "junit:junit:$junit_version"
testImplementation "org.robolectric:robolectric:${robolectric_version}"
testImplementation "net.jodah:concurrentunit:${concurrent_unit_version}"
{{#generateRoomModels}}
annotationProcessor "androidx.room:room-runtime:2.3.0"
implementation "androidx.room:room-runtime:2.3.0"
{{/generateRoomModels}}
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDirectory = project.file("${project.buildDir}/outputs/jar")
task.archiveFileName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
{{#useAndroidMavenGradlePlugin}}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
{{/useAndroidMavenGradlePlugin}}

View File

@ -0,0 +1 @@
{{#isFormParam}}{{{paramName}}}: {{{dataType}}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{/isFormParam}}

View File

@ -0,0 +1,4 @@
{{#generateRoomModels}}
android.useAndroidX=true
android.enableJetifier=true
{{/generateRoomModels}}

View File

@ -0,0 +1 @@
{{#isHeaderParam}}{{{paramName}}}: {{{dataType}}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}{{/isHeaderParam}}

View File

@ -0,0 +1,56 @@
package {{packageName}}.infrastructure
class CollectionFormats {
open class CSVParams {
var params: List<String>
constructor(params: List<String>) {
this.params = params
}
constructor(vararg params: String) {
this.params = listOf(*params)
}
override fun toString(): String {
return params.joinToString(",")
}
}
open class SSVParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString(" ")
}
}
class TSVParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString("\t")
}
}
class PIPESParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString("|")
}
}
class SPACEParams : SSVParams()
}

View File

@ -0,0 +1,9 @@
{{>licenseInfo}}
package {{packageName}}.infrastructure
import {{roomModelPackage}}.*
// TODO ITransformForStorage
interface ITransformForStorage<T> {
fun toRoomModel(): T
}

View File

@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{{packageName}}">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application />
</manifest>

View File

@ -0,0 +1 @@
{{#isPathParam}}{{{paramName}}}: {{{dataType}}}{{/isPathParam}}

View File

@ -0,0 +1 @@
{{#isQueryParam}}{{{paramName}}}: {{#collectionFormat}}{{#isCollectionFormatMulti}}{{{dataType}}}{{/isCollectionFormatMulti}}{{^isCollectionFormatMulti}}{{{collectionFormat.toUpperCase}}}Params{{/isCollectionFormatMulti}}{{/collectionFormat}}{{^collectionFormat}}{{{dataType}}}{{/collectionFormat}}{{^required}}? = null{{/required}}{{/isQueryParam}}

View File

@ -0,0 +1,119 @@
package {{packageName}}.request
import com.android.volley.NetworkResponse
import com.android.volley.ParseError
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.HttpHeaderParser
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.net.HttpURLConnection
import java.lang.reflect.Type
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.OffsetDateTime
import {{packageName}}.infrastructure.OffsetDateTimeAdapter
import {{packageName}}.infrastructure.LocalDateTimeAdapter
import {{packageName}}.infrastructure.LocalDateAdapter
import {{packageName}}.infrastructure.ByteArrayAdapter
class GsonRequest<T>(
method: Int,
url: String,
private val body: Any?,
private val headers: Map<String, String>?,
private val params: MutableMap<String, String>?,
private val contentTypeForBody: String?,
private val encodingForParams: String?,
private val gsonAdapters: Map<Type, Any>?,
private val type: Type,
private val listener: Response.Listener<T>,
errorListener: Response.ErrorListener
) : Request<T>(method, url, errorListener) {
val gsonBuilder: GsonBuilder = GsonBuilder()
.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
.registerTypeAdapter(LocalDateTime::class.java, LocalDateTimeAdapter())
.registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
.registerTypeAdapter(ByteArray::class.java, ByteArrayAdapter())
.apply {
gsonAdapters?.forEach {
this.registerTypeAdapter(it.key, it.value)
}
}
val gson: Gson by lazy {
gsonBuilder.create()
}
private var response: NetworkResponse? = null
override fun deliverResponse(response: T?) {
listener.onResponse(response)
}
override fun getParams(): MutableMap<String, String>? = params ?: super.getParams()
override fun getBodyContentType(): String = contentTypeForBody ?: super.getBodyContentType()
override fun getParamsEncoding(): String = encodingForParams ?: super.getParamsEncoding()
override fun getHeaders(): MutableMap<String, String> {
val combined = HashMap<String, String>()
combined.putAll(super.getHeaders())
if (headers != null) {
combined.putAll(headers)
}
return combined
}
override fun getBody(): ByteArray? {
if (body != null) {
return gson.toJson(body).toByteArray(Charsets.UTF_8)
}
return super.getBody()
}
override fun parseNetworkResponse(response: NetworkResponse?): Response<T> {
return try {
this.response = copyTo(response)
val json = String(
response?.data ?: ByteArray(0),
Charset.forName(HttpHeaderParser.parseCharset(response?.headers))
)
Response.success(
gson.fromJson<T>(json, type),
HttpHeaderParser.parseCacheHeaders(response)
)
} catch (e: UnsupportedEncodingException) {
Response.error(ParseError(e))
} catch (e: JsonSyntaxException) {
Response.error(ParseError(e))
}
}
private fun copyTo(response: NetworkResponse?): NetworkResponse {
return if (response != null) {
NetworkResponse(
response.statusCode,
response.data,
response.notModified,
response.networkTimeMs,
response.allHeaders
)
} else {
// Return an empty response.
NetworkResponse(
HttpURLConnection.HTTP_BAD_METHOD,
ByteArray(0),
false,
0,
emptyList()
)
}
}
}

View File

@ -0,0 +1,64 @@
package {{packageName}}.request
import com.android.volley.Request
import com.android.volley.Response
import java.io.UnsupportedEncodingException
import java.lang.reflect.Type
import java.net.URLEncoder
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.time.format.DateTimeFormatter
import java.time.OffsetDateTime
import java.time.LocalDate
interface IRequestFactory {
companion object {
/**
* ISO 8601 date time format.
* @see https://en.wikipedia.org/wiki/ISO_8601
*/
fun formatDateTime(datetime: OffsetDateTime) = DateTimeFormatter.ISO_INSTANT.format(datetime)
fun formatDate(date: LocalDate) = DateTimeFormatter.ISO_LOCAL_DATE.format(date)
fun escapeString(str: String): String {
return try {
URLEncoder.encode(str, "UTF-8")
} catch (e: UnsupportedEncodingException) {
str
}
}
fun parameterToString(param: Any?) =
when (param) {
null -> ""
is OffsetDateTime -> formatDateTime(param)
is Collection<*> -> {
val b = StringBuilder()
for (o in param) {
if (b.isNotEmpty()) {
b.append(",")
}
b.append(o.toString())
}
b.toString()
}
else -> param.toString()
}
}
fun <T> build(
method: Int,
url : String,
body: Any?,
headers: Map<String, String>?,
queryParams: Map<String, String>?,
formParams: Map<String, String>?,
contentTypeForBody: String?,
type: Type,
responseListener: Response.Listener<T>,
errorListener: Response.ErrorListener): Request<T>
}

View File

@ -0,0 +1,69 @@
// Knowing the details of an operation it will produce a call to a Volley Request constructor
package {{packageName}}.request
import com.android.volley.Request
import com.android.volley.Response
{{#hasAuthMethods}}
import android.util.Base64
{{/hasAuthMethods}}
import {{packageName}}.request.IRequestFactory.Companion.escapeString
import java.lang.reflect.Type
import java.util.Locale
import java.util.UUID
class RequestFactory(private val headerFactories : List<() -> Map<String, String>> = listOf(), private val postProcessors :List <(Request<*>) -> Unit> = listOf(), private val gsonAdapters: Map<Type, Any> = mapOf()): IRequestFactory {
{{#hasAuthMethods}}
{{>auth/authentication}}
{{/hasAuthMethods}}
/**
* {@inheritDoc}
*/
@Suppress("UNCHECKED_CAST")
override fun <T> build(
method: Int,
url: String,
body: Any?,
headers: Map<String, String>?,
queryParams: Map<String, String>?,
formParams: Map<String, String>?,
contentTypeForBody: String?,
type: Type,
responseListener: Response.Listener<T>,
errorListener: Response.ErrorListener
): Request<T> {
val afterMarketHeaders = (headers?.toMutableMap() ?: mutableMapOf())
// Factory built and aftermarket
// Merge the after market headers on top of the base ones in case we are overriding per call auth
val allHeaders = headerFactories.fold(afterMarketHeaders) { acc, factory -> (acc + factory.invoke()).toMutableMap() }
// If we decide to support auth parameters in the url, then you will reference them by supplying a url string
// with known variable name refernces in the string. We will then apply
val updatedUrl = if (!queryParams.isNullOrEmpty()) {
queryParams.asSequence().fold("$url?") {acc, param ->
"$acc${escapeString(param.key)}=${escapeString(param.value)}&"
}.trimEnd('&')
} else {
url
}
val request = GsonRequest(
method,
updatedUrl,
body,
allHeaders,
formParams?.toMutableMap(),
contentTypeForBody,
null,
gsonAdapters,
type,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
return request
}
}

View File

@ -0,0 +1,38 @@
{{>licenseInfo}}
package {{roomModelPackage}}
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import {{modelPackage}}.*
{{#models}}
{{#model}}
@Entity(tableName = "{{classname}}")
/**
* Room model for {{{description}}}
{{#allVars}}
* @param {{{name}}} {{{description}}}
{{/allVars}}
*/
data class {{classname}}RoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
{{#allVars}}{{#items.isPrimitiveType}}var {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInCamelCase}}}{{/items.isEnum}}>{{>model_room_init_var}}{{/isArray}},
{{/items.isPrimitiveType}}{{/allVars}}
{{#allVars}}{{^isEnum}}{{^isArray}}var {{{name}}}: {{{dataType}}}{{>model_room_init_var}},
{{/isArray}}{{/isEnum}}{{/allVars}}
{{#allVars}}{{#isEnum}}{{^isArray}}var {{{name}}}: {{classname}}.{{{nameInCamelCase}}}{{>model_room_init_var}},
{{/isArray}}{{/isEnum}}{{/allVars}}) {
{{#allVars}}{{#isArray}}{{#isList}}{{^items.isPrimitiveType}}
@Ignore
{{^isNullable}}{{#required}}lateinit {{/required}}{{/isNullable}}var {{{name}}}: {{#isArray}}{{#isList}}kotlin.collections.List{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInCamelCase}}}{{/items.isEnum}}>{{>model_room_init_var}}{{/isArray}}
{{/items.isPrimitiveType}}{{/isList}}{{/isArray}}{{/allVars}}
{{^discriminator}}companion object { }
fun toApiModel(): {{classname}} = {{classname}}(
{{#allVars}}{{name}} = this.{{name}},
{{/allVars}}){{/discriminator}}
}
{{/model}}
{{/models}}

View File

@ -0,0 +1 @@
{{#isNullable}}?{{/isNullable}}{{^required}}?{{/required}}{{#defaultvalue}} = {{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}{{#isNullable}} = null{{/isNullable}}{{^required}} = null{{/required}}{{/defaultvalue}}

View File

@ -187,4 +187,14 @@ public class TestUtils {
for (String line : lines)
assertFalse(file.contains(linearize(line)));
}
public static void assertFileNotExists(Path path) {
try {
new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
fail("File exists when it should not: " + path);
} catch (IOException e) {
// File exists, pass.
assertTrue(true);
}
}
}

View File

@ -0,0 +1,83 @@
package org.openapitools.codegen.kotlin.jvm_volley;
import io.swagger.parser.OpenAPIParser;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.core.models.ParseOptions;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
import org.openapitools.codegen.languages.KotlinClientCodegen;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.openapitools.codegen.TestUtils.*;
public class KotlinJvmVolleyModelCodegenTest {
@Test
public void modelsWithRoomModels() throws IOException {
KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.additionalProperties().put(KotlinClientCodegen.GENERATE_ROOM_MODELS, true);
codegen.additionalProperties().put(KotlinClientCodegen.ROOM_MODEL_PACKAGE, "models.room");
codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, AbstractKotlinCodegen.SERIALIZATION_LIBRARY_TYPE.gson.name());
String outputPath = checkModel(codegen, false);
assertFileContains(Paths.get(outputPath + "/src/main/java/models/room/BigDogRoomModel.kt"), "toApiModel()");
assertFileContains(Paths.get(outputPath + "/src/main/java/models/BigDog.kt"), "toRoomModel()");
}
@Test
public void modelsWithoutRoomModels() throws IOException {
KotlinClientCodegen codegen = new KotlinClientCodegen();
codegen.additionalProperties().put(KotlinClientCodegen.GENERATE_ROOM_MODELS, false);
codegen.additionalProperties().put(CodegenConstants.SERIALIZATION_LIBRARY, AbstractKotlinCodegen.SERIALIZATION_LIBRARY_TYPE.gson.name());
String outputPath = checkModel(codegen, false);
assertFileNotExists(Paths.get(outputPath + "/src/main/java/models/room/BigDogRoomModel.kt"));
assertFileContains(Paths.get(outputPath + "/src/main/java/models/BigDog.kt"));
assertFileNotContains(Paths.get(outputPath + "/src/main/java/models/BigDog.kt"), "toRoomModel()");
}
private String checkModel(AbstractKotlinCodegen codegen, boolean mutable, String... props) throws IOException {
String outputPath = generateModels(codegen, "src/test/resources/3_0/generic.yaml", mutable);
assertFileContains(Paths.get(outputPath + "/src/main/java/models/Animal.kt"), props);
return outputPath;
}
private String generateModels(AbstractKotlinCodegen codegen, String fileName, boolean mutable) throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');
OpenAPI openAPI = new OpenAPIParser()
.readLocation(fileName, null, new ParseOptions()).getOpenAPI();
codegen.setOutputDir(output.getAbsolutePath());
codegen.setLibrary("jvm-volley");
codegen.additionalProperties().put(CodegenConstants.MODEL_PACKAGE, "models");
codegen.additionalProperties().put(AbstractKotlinCodegen.MODEL_MUTABLE, mutable);
ClientOptInput input = new ClientOptInput()
.openAPI(openAPI)
.config(codegen);
DefaultGenerator generator = new DefaultGenerator();
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "true");
generator.opts(input).generate();
return outputPath;
}
}

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1,43 @@
README.md
build.gradle
docs/ApiResponse.md
docs/Category.md
docs/Order.md
docs/Pet.md
docs/PetApi.md
docs/StoreApi.md
docs/Tag.md
docs/User.md
docs/UserApi.md
gradle.properties
gradle/wrapper/gradle-wrapper.jar
gradle/wrapper/gradle-wrapper.properties
gradlew
gradlew.bat
settings.gradle
src/main/AndroidManifest.xml
src/main/java/org/openapitools/client/apis/PetApi.kt
src/main/java/org/openapitools/client/apis/StoreApi.kt
src/main/java/org/openapitools/client/apis/UserApi.kt
src/main/java/org/openapitools/client/infrastructure/ByteArrayAdapter.kt
src/main/java/org/openapitools/client/infrastructure/CollectionFormats.kt
src/main/java/org/openapitools/client/infrastructure/CollectionFormats.kt
src/main/java/org/openapitools/client/infrastructure/ITransformForStorage.kt
src/main/java/org/openapitools/client/infrastructure/LocalDateAdapter.kt
src/main/java/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt
src/main/java/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt
src/main/java/org/openapitools/client/models/Category.kt
src/main/java/org/openapitools/client/models/ModelApiResponse.kt
src/main/java/org/openapitools/client/models/Order.kt
src/main/java/org/openapitools/client/models/Pet.kt
src/main/java/org/openapitools/client/models/Tag.kt
src/main/java/org/openapitools/client/models/User.kt
src/main/java/org/openapitools/client/models/room/CategoryRoomModel.kt
src/main/java/org/openapitools/client/models/room/ModelApiResponseRoomModel.kt
src/main/java/org/openapitools/client/models/room/OrderRoomModel.kt
src/main/java/org/openapitools/client/models/room/PetRoomModel.kt
src/main/java/org/openapitools/client/models/room/TagRoomModel.kt
src/main/java/org/openapitools/client/models/room/UserRoomModel.kt
src/main/java/org/openapitools/client/request/GsonRequest.kt
src/main/java/org/openapitools/client/request/IRequestFactory.kt
src/main/java/org/openapitools/client/request/RequestFactory.kt

View File

@ -0,0 +1 @@
5.3.1-SNAPSHOT

View File

@ -0,0 +1,230 @@
# org.openapitools.client - Kotlin client library for OpenAPI Petstore
A kotlin client for Android using the currently recommended http client, Volley. See https://developer.android.com/training/volley
- Currently sends GsonRequests
- Currently only supports Gson as a serializer - will throw an exception if a different serializer is chosen
- Defaults the source location to src/main/java as per standard Android builds
## Design
Volley is a queue/request based layer on top of http url stack specific to Android. Android favours dependency injection and
a layered architecture, and IO performed off the main thread to maintain UI responsiveness, with a preferred technique of
kotlin co-routines. The code gen library reflects these factors.
- Api calls use co-routines, and execute them using volley callbacks to avoid tying up a thread.
- Facilitate dependency injection, with default implementations available.
- Generate a requestFactory that can be overridden
- Allow the passing of the RequestFactory per tag (api client) or per operation (an extra parameter is created on operations with non-global security), with per operation auth overriding global security.
- DI scoping of the Request Factory and pre-generated auth header factories allow for thread safe and secure setting of credentials.
- Lazy header factories allow for refreshing tokens etc
- Factoring of header factories to the Request Factory allow ambient provision of credentials. Code gen library is credential storage agnostic.
- Header factories allow the merging of generated headers from open api spec with dynamically added headers
- Injection of http url stack to allow custom http stacks. Default implementation is best practice singleton
- Data classes used for serialisation to reflect volley's preference - an immutable request that once queued can't be tampered with.
- Reuse model class and other jvm common infrastructure
- Optional generation of room database models, and transform methods to these from open api models
- Room and api models can be extended with additional extension properties.
## Future improvements
- Option to generate image requests on certain conditionals e.g content-type gif etc
- Support for kotlin serialization.
- Multi part form parameters and support for file inputs
## Usage
Hilt Dependency injection example - with default values for parameters overridden.
```
@Provides
internal fun provideSomeApi(
context: Context,
restService: IRestService,
configurationService: IConfigurationService,
sessionService: ISessionService
): SomeApi {
return SomeApi(
context = context,
requestQueue = restService.getRequestQueue(),
requestFactory = RequestFactory(listOf(createSessionHeaderFactory(sessionService), createTraceHeaderFactory()),
postProcessors = listOf(retryPolicySetter)),
basePath = configurationService.getBaseUrl()
)
}
```
Here is the constructor so you can see the defaults
```class SomeApi (
val context: Context,
val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
val requestFactory: IRequestFactory = RequestFactory(),
val basePath: String = "https://yourbasepath.from_input_parameter.com/api",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
```
### Overriding defaults
The above constructor for each api allows the following to be customized
- A custom context, so either a singleton request queue or different scope can be created - see
https://developer.android.com/training/volley/requestqueue#singleton
- An overrideable request queue - which in turn can have a custom http url stack passed to it
- An overrideable request factory constructor call, or a request factory that can be overridden by a custom template, with
custom header factory, request post processors and custom gson adapters injected.
#### Overriding request generation
Request generation can be overridden by
- Overriding the entire request factory template
- Supplying custom header factories - methods that take any possible parameters but return a map of headers
- Supplying custom request post processors - methods that take and return the request object
Header factory examples can be found in the auth section, as these are implemented as header factories. eg
```
val basicAuthHeaderFactoryBuilder = { username: String?, password: String? ->
{ mapOf("Authorization" to "Basic " + Base64.encodeToString("${username ?: ""}:${password ?: ""}".toByteArray(), Base64.DEFAULT))}
}
```
In this case it's a lambda function (a factory method) that takes an username and password, and returns a map of headers. Other
generated code will supply the username and password. In this case it results in a map of just one key/value pair, but
it could be multiple. The important part is it's returning a map - and that the surrounding code
will can bind the inputs to it at some point.
Here is a different example that supplies tracing header values
```
/**
* Create a lambda of tracing headers to be injected into an API's [RequestFactory].
*/
private fun createTraceHeaderFactory(): () -> Map<String, String> = {
mapOf(
HttpHeaderType.b3_traceId.rawValue to UUIDExtensions.asTraceId(UUID.randomUUID()),
HttpHeaderType.b3_spanId.rawValue to UUIDExtensions.asSpanId(UUID.randomUUID()),
HttpHeaderType.b3_sampled.rawValue to "1"
)
}
```
Finally a post processor example
```
/**
* Configure a [DefaultRetryPolicy] to be injected into the [RequestFactory] with a maximum number of retries of zero.
*/
private val retryPolicySetter = { request: Request<*> ->
Unit.apply {
request.setRetryPolicy(
DefaultRetryPolicy(
RestService.DEFAULT_TIMEOUT_MS,
0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
)
}
}
```
### Serialization
#### Gson and Polymorphic types
The GsonRequest object can be passed custom type adapters
```
class GsonRequest<T>(
method: Int,
url: String,
private val body: Any?,
private val headers: Map<String, String>?,
private val params: MutableMap<String, String>?,
private val contentTypeForBody: String?,
private val encodingForParams: String?,
private val gsonAdapters: Map<Type, Object>?,
private val type: Type,
private val listener: Response.Listener<T>,
errorListener: Response.ErrorListener
) : Request<T>(method, url, errorListener) {
val gsonBuilder: GsonBuilder = GsonBuilder()
.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
.registerTypeAdapter(LocalDateTime::class.java, LocalDateTimeAdapter())
.registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
.registerTypeAdapter(ByteArray::class.java, ByteArrayAdapter())
```
## Requires
* Kotlin 1.4.30
* Gradle 6.8.3
## Build
First, create the gradle wrapper script:
```
gradle wrapper
```
Then, run:
```
./gradlew check assemble
```
This runs all tests and packages the library.
<a name="documentation-for-api-endpoints"></a>
## Documentation for API Endpoints
All URIs are relative to *http://petstore.swagger.io/v2*
Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*PetApi* | [**addPet**](docs/PetApi.md#addpet) | **POST** /pet | Add a new pet to the store
*PetApi* | [**deletePet**](docs/PetApi.md#deletepet) | **DELETE** /pet/{petId} | Deletes a pet
*PetApi* | [**findPetsByStatus**](docs/PetApi.md#findpetsbystatus) | **GET** /pet/findByStatus | Finds Pets by status
*PetApi* | [**findPetsByTags**](docs/PetApi.md#findpetsbytags) | **GET** /pet/findByTags | Finds Pets by tags
*PetApi* | [**getPetById**](docs/PetApi.md#getpetbyid) | **GET** /pet/{petId} | Find pet by ID
*PetApi* | [**updatePet**](docs/PetApi.md#updatepet) | **PUT** /pet | Update an existing pet
*PetApi* | [**updatePetWithForm**](docs/PetApi.md#updatepetwithform) | **POST** /pet/{petId} | Updates a pet in the store with form data
*PetApi* | [**uploadFile**](docs/PetApi.md#uploadfile) | **POST** /pet/{petId}/uploadImage | uploads an image
*StoreApi* | [**deleteOrder**](docs/StoreApi.md#deleteorder) | **DELETE** /store/order/{orderId} | Delete purchase order by ID
*StoreApi* | [**getInventory**](docs/StoreApi.md#getinventory) | **GET** /store/inventory | Returns pet inventories by status
*StoreApi* | [**getOrderById**](docs/StoreApi.md#getorderbyid) | **GET** /store/order/{orderId} | Find purchase order by ID
*StoreApi* | [**placeOrder**](docs/StoreApi.md#placeorder) | **POST** /store/order | Place an order for a pet
*UserApi* | [**createUser**](docs/UserApi.md#createuser) | **POST** /user | Create user
*UserApi* | [**createUsersWithArrayInput**](docs/UserApi.md#createuserswitharrayinput) | **POST** /user/createWithArray | Creates list of users with given input array
*UserApi* | [**createUsersWithListInput**](docs/UserApi.md#createuserswithlistinput) | **POST** /user/createWithList | Creates list of users with given input array
*UserApi* | [**deleteUser**](docs/UserApi.md#deleteuser) | **DELETE** /user/{username} | Delete user
*UserApi* | [**getUserByName**](docs/UserApi.md#getuserbyname) | **GET** /user/{username} | Get user by user name
*UserApi* | [**loginUser**](docs/UserApi.md#loginuser) | **GET** /user/login | Logs user into the system
*UserApi* | [**logoutUser**](docs/UserApi.md#logoutuser) | **GET** /user/logout | Logs out current logged in user session
*UserApi* | [**updateUser**](docs/UserApi.md#updateuser) | **PUT** /user/{username} | Updated user
<a name="documentation-for-models"></a>
## Documentation for Models
- [org.openapitools.client.models.Category](docs/Category.md)
- [org.openapitools.client.models.ModelApiResponse](docs/ModelApiResponse.md)
- [org.openapitools.client.models.Order](docs/Order.md)
- [org.openapitools.client.models.Pet](docs/Pet.md)
- [org.openapitools.client.models.Tag](docs/Tag.md)
- [org.openapitools.client.models.User](docs/User.md)
<a name="documentation-for-authorization"></a>
## Documentation for Authorization
<a name="api_key"></a>
### api_key
- **Type**: API key
- **API key parameter name**: api_key
- **Location**: HTTP header
<a name="petstore_auth"></a>
### petstore_auth
- **Type**: OAuth
- **Flow**: implicit
- **Authorization URL**: http://petstore.swagger.io/api/oauth/dialog
- **Scopes**:
- write:pets: modify pets in your account
- read:pets: read your pets

View File

@ -0,0 +1,95 @@
buildscript {
ext.kotlin_version = '1.5.10'
ext.swagger_annotations_version = "1.6.2"
ext.gson_version = "2.8.6"
ext.volley_version = "1.2.0"
ext.junit_version = "4.13.2"
ext.robolectric_version = "4.5.1"
ext.concurrent_unit_version = "0.4.6"
repositories {
mavenLocal()
google()
maven {
url 'https://dl.google.com/dl/android/maven2'
}
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.android.tools.build:gradle:4.0.2'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
// Rename the aar correctly
libraryVariants.all { variant ->
variant.outputs.all { output ->
if (outputFile != null && outputFileName.endsWith('.aar')) {
outputFileName = "${archivesBaseName}-${version}.aar"
}
}
}
testOptions {
unitTests.returnDefaultValues = true
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
implementation "com.google.code.gson:gson:$gson_version"
implementation "com.android.volley:volley:${volley_version}"
testImplementation "junit:junit:$junit_version"
testImplementation "org.robolectric:robolectric:${robolectric_version}"
testImplementation "net.jodah:concurrentunit:${concurrent_unit_version}"
annotationProcessor "androidx.room:room-runtime:2.3.0"
implementation "androidx.room:room-runtime:2.3.0"
}
afterEvaluate {
android.libraryVariants.all { variant ->
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
task.destinationDirectory = project.file("${project.buildDir}/outputs/jar")
task.archiveFileName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}

View File

@ -0,0 +1,12 @@
# ModelApiResponse
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**code** | **kotlin.Int** | | [optional]
**type** | **kotlin.String** | | [optional]
**message** | **kotlin.String** | | [optional]

View File

@ -0,0 +1,11 @@
# Category
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **kotlin.Long** | | [optional]
**name** | **kotlin.String** | | [optional]

View File

@ -0,0 +1,22 @@
# Order
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **kotlin.Long** | | [optional]
**petId** | **kotlin.Long** | | [optional]
**quantity** | **kotlin.Int** | | [optional]
**shipDate** | [**java.time.OffsetDateTime**](java.time.OffsetDateTime.md) | | [optional]
**status** | [**inline**](#Status) | Order Status | [optional]
**complete** | **kotlin.Boolean** | | [optional]
<a name="Status"></a>
## Enum: status
Name | Value
---- | -----
status | placed, approved, delivered

View File

@ -0,0 +1,22 @@
# Pet
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **kotlin.String** | |
**photoUrls** | **kotlin.collections.List&lt;kotlin.String&gt;** | |
**id** | **kotlin.Long** | | [optional]
**category** | [**Category**](Category.md) | | [optional]
**tags** | [**kotlin.collections.List&lt;Tag&gt;**](Tag.md) | | [optional]
**status** | [**inline**](#Status) | pet status in the store | [optional]
<a name="Status"></a>
## Enum: status
Name | Value
---- | -----
status | available, pending, sold

View File

@ -0,0 +1,320 @@
# PetApi
All URIs are relative to *http://petstore.swagger.io/v2*
Method | HTTP request | Description
------------- | ------------- | -------------
[**addPet**](PetApi.md#addPet) | **POST** /pet | Add a new pet to the store
[**deletePet**](PetApi.md#deletePet) | **DELETE** /pet/{petId} | Deletes a pet
[**findPetsByStatus**](PetApi.md#findPetsByStatus) | **GET** /pet/findByStatus | Finds Pets by status
[**findPetsByTags**](PetApi.md#findPetsByTags) | **GET** /pet/findByTags | Finds Pets by tags
[**getPetById**](PetApi.md#getPetById) | **GET** /pet/{petId} | Find pet by ID
[**updatePet**](PetApi.md#updatePet) | **PUT** /pet | Update an existing pet
[**updatePetWithForm**](PetApi.md#updatePetWithForm) | **POST** /pet/{petId} | Updates a pet in the store with form data
[**uploadFile**](PetApi.md#uploadFile) | **POST** /pet/{petId}/uploadImage | uploads an image
Add a new pet to the store
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val body : Pet = // Pet | Pet object that needs to be added to the store
webService.addPet(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**Pet**](Pet.md)| Pet object that needs to be added to the store |
### Return type
null (empty response body)
### Authorization
### HTTP request headers
- **Content-Type**: application/json, application/xml
- **Accept**: Not defined
Deletes a pet
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val petId : kotlin.Long = 789 // kotlin.Long | Pet id to delete
val apiKey : kotlin.String = apiKey_example // kotlin.String |
webService.deletePet(petId, apiKey)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**petId** | **kotlin.Long**| Pet id to delete |
**apiKey** | **kotlin.String**| | [optional]
### Return type
null (empty response body)
### Authorization
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Finds Pets by status
Multiple status values can be provided with comma separated strings
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val status : kotlin.collections.List<kotlin.String> = // kotlin.collections.List<kotlin.String> | Status values that need to be considered for filter
val result : kotlin.collections.List<Pet> = webService.findPetsByStatus(status)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**status** | [**kotlin.collections.List&lt;kotlin.String&gt;**](kotlin.String.md)| Status values that need to be considered for filter | [enum: available, pending, sold]
### Return type
[**kotlin.collections.List&lt;Pet&gt;**](Pet.md)
### Authorization
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val tags : kotlin.collections.List<kotlin.String> = // kotlin.collections.List<kotlin.String> | Tags to filter by
val result : kotlin.collections.List<Pet> = webService.findPetsByTags(tags)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**tags** | [**kotlin.collections.List&lt;kotlin.String&gt;**](kotlin.String.md)| Tags to filter by |
### Return type
[**kotlin.collections.List&lt;Pet&gt;**](Pet.md)
### Authorization
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Find pet by ID
Returns a single pet
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to return
val result : Pet = webService.getPetById(petId)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**petId** | **kotlin.Long**| ID of pet to return |
### Return type
[**Pet**](Pet.md)
### Authorization
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Update an existing pet
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val body : Pet = // Pet | Pet object that needs to be added to the store
webService.updatePet(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**Pet**](Pet.md)| Pet object that needs to be added to the store |
### Return type
null (empty response body)
### Authorization
### HTTP request headers
- **Content-Type**: application/json, application/xml
- **Accept**: Not defined
Updates a pet in the store with form data
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet that needs to be updated
val name : kotlin.String = name_example // kotlin.String | Updated name of the pet
val status : kotlin.String = status_example // kotlin.String | Updated status of the pet
webService.updatePetWithForm(petId, name, status)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**petId** | **kotlin.Long**| ID of pet that needs to be updated |
**name** | **kotlin.String**| Updated name of the pet | [optional]
**status** | **kotlin.String**| Updated status of the pet | [optional]
### Return type
null (empty response body)
### Authorization
### HTTP request headers
- **Content-Type**: application/x-www-form-urlencoded
- **Accept**: Not defined
uploads an image
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(PetApi::class.java)
val petId : kotlin.Long = 789 // kotlin.Long | ID of pet to update
val additionalMetadata : kotlin.String = additionalMetadata_example // kotlin.String | Additional data to pass to server
val file : java.io.File = BINARY_DATA_HERE // java.io.File | file to upload
val result : ModelApiResponse = webService.uploadFile(petId, additionalMetadata, file)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**petId** | **kotlin.Long**| ID of pet to update |
**additionalMetadata** | **kotlin.String**| Additional data to pass to server | [optional]
**file** | **java.io.File**| file to upload | [optional]
### Return type
[**ModelApiResponse**](ModelApiResponse.md)
### Authorization
### HTTP request headers
- **Content-Type**: multipart/form-data
- **Accept**: application/json

View File

@ -0,0 +1,158 @@
# StoreApi
All URIs are relative to *http://petstore.swagger.io/v2*
Method | HTTP request | Description
------------- | ------------- | -------------
[**deleteOrder**](StoreApi.md#deleteOrder) | **DELETE** /store/order/{orderId} | Delete purchase order by ID
[**getInventory**](StoreApi.md#getInventory) | **GET** /store/inventory | Returns pet inventories by status
[**getOrderById**](StoreApi.md#getOrderById) | **GET** /store/order/{orderId} | Find purchase order by ID
[**placeOrder**](StoreApi.md#placeOrder) | **POST** /store/order | Place an order for a pet
Delete purchase order by ID
For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(StoreApi::class.java)
val orderId : kotlin.String = orderId_example // kotlin.String | ID of the order that needs to be deleted
webService.deleteOrder(orderId)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**orderId** | **kotlin.String**| ID of the order that needs to be deleted |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Returns pet inventories by status
Returns a map of status codes to quantities
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(StoreApi::class.java)
val result : kotlin.collections.Map<kotlin.String, kotlin.Int> = webService.getInventory()
```
### Parameters
This endpoint does not need any parameter.
### Return type
**kotlin.collections.Map&lt;kotlin.String, kotlin.Int&gt;**
### Authorization
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
Find purchase order by ID
For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(StoreApi::class.java)
val orderId : kotlin.Long = 789 // kotlin.Long | ID of pet that needs to be fetched
val result : Order = webService.getOrderById(orderId)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**orderId** | **kotlin.Long**| ID of pet that needs to be fetched |
### Return type
[**Order**](Order.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Place an order for a pet
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(StoreApi::class.java)
val body : Order = // Order | order placed for purchasing the pet
val result : Order = webService.placeOrder(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**Order**](Order.md)| order placed for purchasing the pet |
### Return type
[**Order**](Order.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json

View File

@ -0,0 +1,11 @@
# Tag
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **kotlin.Long** | | [optional]
**name** | **kotlin.String** | | [optional]

View File

@ -0,0 +1,17 @@
# User
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**id** | **kotlin.Long** | | [optional]
**username** | **kotlin.String** | | [optional]
**firstName** | **kotlin.String** | | [optional]
**lastName** | **kotlin.String** | | [optional]
**email** | **kotlin.String** | | [optional]
**password** | **kotlin.String** | | [optional]
**phone** | **kotlin.String** | | [optional]
**userStatus** | **kotlin.Int** | User Status | [optional]

View File

@ -0,0 +1,310 @@
# UserApi
All URIs are relative to *http://petstore.swagger.io/v2*
Method | HTTP request | Description
------------- | ------------- | -------------
[**createUser**](UserApi.md#createUser) | **POST** /user | Create user
[**createUsersWithArrayInput**](UserApi.md#createUsersWithArrayInput) | **POST** /user/createWithArray | Creates list of users with given input array
[**createUsersWithListInput**](UserApi.md#createUsersWithListInput) | **POST** /user/createWithList | Creates list of users with given input array
[**deleteUser**](UserApi.md#deleteUser) | **DELETE** /user/{username} | Delete user
[**getUserByName**](UserApi.md#getUserByName) | **GET** /user/{username} | Get user by user name
[**loginUser**](UserApi.md#loginUser) | **GET** /user/login | Logs user into the system
[**logoutUser**](UserApi.md#logoutUser) | **GET** /user/logout | Logs out current logged in user session
[**updateUser**](UserApi.md#updateUser) | **PUT** /user/{username} | Updated user
Create user
This can only be done by the logged in user.
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val body : User = // User | Created user object
webService.createUser(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**User**](User.md)| Created user object |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Creates list of users with given input array
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val body : kotlin.collections.List<User> = // kotlin.collections.List<User> | List of user object
webService.createUsersWithArrayInput(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**kotlin.collections.List&lt;User&gt;**](User.md)| List of user object |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Creates list of users with given input array
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val body : kotlin.collections.List<User> = // kotlin.collections.List<User> | List of user object
webService.createUsersWithListInput(body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**body** | [**kotlin.collections.List&lt;User&gt;**](User.md)| List of user object |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Delete user
This can only be done by the logged in user.
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val username : kotlin.String = username_example // kotlin.String | The name that needs to be deleted
webService.deleteUser(username)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**username** | **kotlin.String**| The name that needs to be deleted |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Get user by user name
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val username : kotlin.String = username_example // kotlin.String | The name that needs to be fetched. Use user1 for testing.
val result : User = webService.getUserByName(username)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**username** | **kotlin.String**| The name that needs to be fetched. Use user1 for testing. |
### Return type
[**User**](User.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Logs user into the system
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val username : kotlin.String = username_example // kotlin.String | The user name for login
val password : kotlin.String = password_example // kotlin.String | The password for login in clear text
val result : kotlin.String = webService.loginUser(username, password)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**username** | **kotlin.String**| The user name for login |
**password** | **kotlin.String**| The password for login in clear text |
### Return type
**kotlin.String**
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/xml, application/json
Logs out current logged in user session
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
webService.logoutUser()
```
### Parameters
This endpoint does not need any parameter.
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined
Updated user
This can only be done by the logged in user.
### Example
```kotlin
// Import classes:
//import org.openapitools.client.*
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*
val apiClient = ApiClient()
val webService = apiClient.createWebservice(UserApi::class.java)
val username : kotlin.String = username_example // kotlin.String | name that need to be deleted
val body : User = // User | Updated user object
webService.updateUser(username, body)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**username** | **kotlin.String**| name that need to be deleted |
**body** | [**User**](User.md)| Updated user object |
### Return type
null (empty response body)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: Not defined

View File

@ -0,0 +1,2 @@
android.useAndroidX=true
android.enableJetifier=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,2 @@
rootProject.name = 'kotlin-petstore-jvm-volley'

View File

@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.openapitools.client">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application />
</manifest>

View File

@ -0,0 +1,586 @@
package org.openapitools.client.apis
import android.content.Context
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.BaseHttpStack
import com.android.volley.toolbox.Volley
import java.util.*;
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import com.google.gson.reflect.TypeToken
import org.openapitools.client.request.IRequestFactory
import org.openapitools.client.request.RequestFactory
import org.openapitools.client.infrastructure.CollectionFormats.*
import org.openapitools.client.models.ModelApiResponse
import org.openapitools.client.models.Pet
/*
* If you wish to use a custom http stack with your client you
* can pass that to the request queue like:
* Volley.newRequestQueue(context.applicationContext, myCustomHttpStack)
*/
class PetApi (
private val context: Context,
private val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
private val requestFactory: IRequestFactory = RequestFactory(),
private val basePath: String = "http://petstore.swagger.io/v2",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
/**
* Add a new pet to the store
*
* @param body Pet object that needs to be added to the store
* @return void
*/
suspend fun addPet(body: Pet): Unit {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf("application/json","application/xml")
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Deletes a pet
*
* @param petId Pet id to delete
* @param apiKey
* @return void
*/
suspend fun deletePet(petId: kotlin.Long, apiKey: kotlin.String? = null): Unit {
val body: Any? = null
// verify the required parameter 'petId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(petId)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/{petId}".replace("{" + "petId" + "}", IRequestFactory.escapeString(petId.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
"api_key" to IRequestFactory.parameterToString(apiKey),
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.DELETE,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* 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.collections.List<Pet>
*/
suspend fun findPetsByStatus(status: CSVParams): kotlin.collections.List<Pet>? {
val body: Any? = null
// verify the required parameter 'status' is set
// This is probably taken care of by non-null types anyway
requireNotNull(status)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/findByStatus";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
"status" to IRequestFactory.parameterToString(status),
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<kotlin.collections.List<Pet>> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<kotlin.collections.List<Pet>>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<kotlin.collections.List<Pet>> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* 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.collections.List<Pet>
*/
@Deprecated("This api was deprecated")
suspend fun findPetsByTags(tags: CSVParams): kotlin.collections.List<Pet>? {
val body: Any? = null
// verify the required parameter 'tags' is set
// This is probably taken care of by non-null types anyway
requireNotNull(tags)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/findByTags";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
"tags" to IRequestFactory.parameterToString(tags),
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<kotlin.collections.List<Pet>> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<kotlin.collections.List<Pet>>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<kotlin.collections.List<Pet>> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Find pet by ID
* Returns a single pet
* @param petId ID of pet to return
* @return Pet
*/
suspend fun getPetById(petId: kotlin.Long): Pet? {
val body: Any? = null
// verify the required parameter 'petId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(petId)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/{petId}".replace("{" + "petId" + "}", IRequestFactory.escapeString(petId.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Pet> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Pet>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Pet> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Update an existing pet
*
* @param body Pet object that needs to be added to the store
* @return void
*/
suspend fun updatePet(body: Pet): Unit {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf("application/json","application/xml")
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.PUT,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* 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
* @param status Updated status of the pet
* @return void
*/
suspend fun updatePetWithForm(petId: kotlin.Long, name: kotlin.String? = null, status: kotlin.String? = null): Unit {
val body: Any? = null
// verify the required parameter 'petId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(petId)
val contentTypes : Array<String> = arrayOf("application/x-www-form-urlencoded")
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/{petId}".replace("{" + "petId" + "}", IRequestFactory.escapeString(petId.toString()));
// form params
val formParams = mapOf<String, String>(
"name" to IRequestFactory.parameterToString(name),
"status" to IRequestFactory.parameterToString(status),
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* uploads an image
*
* @param petId ID of pet to update
* @param additionalMetadata Additional data to pass to server
* @param file file to upload
* @return ModelApiResponse
*/
suspend fun uploadFile(petId: kotlin.Long, additionalMetadata: kotlin.String? = null, file: java.io.File? = null): ModelApiResponse? {
val body: Any? = null
// verify the required parameter 'petId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(petId)
val contentTypes : Array<String> = arrayOf("multipart/form-data")
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/pet/{petId}/uploadImage".replace("{" + "petId" + "}", IRequestFactory.escapeString(petId.toString()));
// form params
val formParams = mapOf<String, String>(
"additionalMetadata" to IRequestFactory.parameterToString(additionalMetadata),
"file" to IRequestFactory.parameterToString(file),
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<ModelApiResponse> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<ModelApiResponse>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<ModelApiResponse> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
}

View File

@ -0,0 +1,300 @@
package org.openapitools.client.apis
import android.content.Context
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.BaseHttpStack
import com.android.volley.toolbox.Volley
import java.util.*;
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import com.google.gson.reflect.TypeToken
import org.openapitools.client.request.IRequestFactory
import org.openapitools.client.request.RequestFactory
import org.openapitools.client.infrastructure.CollectionFormats.*
import org.openapitools.client.models.Order
/*
* If you wish to use a custom http stack with your client you
* can pass that to the request queue like:
* Volley.newRequestQueue(context.applicationContext, myCustomHttpStack)
*/
class StoreApi (
private val context: Context,
private val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
private val requestFactory: IRequestFactory = RequestFactory(),
private val basePath: String = "http://petstore.swagger.io/v2",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
/**
* Delete purchase order by ID
* For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors
* @param orderId ID of the order that needs to be deleted
* @return void
*/
suspend fun deleteOrder(orderId: kotlin.String): Unit {
val body: Any? = null
// verify the required parameter 'orderId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(orderId)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/store/order/{orderId}".replace("{" + "orderId" + "}", IRequestFactory.escapeString(orderId.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.DELETE,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Returns pet inventories by status
* Returns a map of status codes to quantities
* @return kotlin.collections.Map<kotlin.String, kotlin.Int>
*/
suspend fun getInventory(): kotlin.collections.Map<kotlin.String, kotlin.Int>? {
val body: Any? = null
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/store/inventory";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<kotlin.collections.Map<kotlin.String, kotlin.Int>> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<kotlin.collections.Map<kotlin.String, kotlin.Int>>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<kotlin.collections.Map<kotlin.String, kotlin.Int>> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Find purchase order by ID
* For valid response try integer IDs with value &lt;&#x3D; 5 or &gt; 10. Other values will generated exceptions
* @param orderId ID of pet that needs to be fetched
* @return Order
*/
suspend fun getOrderById(orderId: kotlin.Long): Order? {
val body: Any? = null
// verify the required parameter 'orderId' is set
// This is probably taken care of by non-null types anyway
requireNotNull(orderId)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/store/order/{orderId}".replace("{" + "orderId" + "}", IRequestFactory.escapeString(orderId.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Order> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Order>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Order> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Place an order for a pet
*
* @param body order placed for purchasing the pet
* @return Order
*/
suspend fun placeOrder(body: Order): Order? {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/store/order";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Order> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Order>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Order> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
}

View File

@ -0,0 +1,578 @@
package org.openapitools.client.apis
import android.content.Context
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.Response
import com.android.volley.toolbox.BaseHttpStack
import com.android.volley.toolbox.Volley
import java.util.*;
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import com.google.gson.reflect.TypeToken
import org.openapitools.client.request.IRequestFactory
import org.openapitools.client.request.RequestFactory
import org.openapitools.client.infrastructure.CollectionFormats.*
import org.openapitools.client.models.User
/*
* If you wish to use a custom http stack with your client you
* can pass that to the request queue like:
* Volley.newRequestQueue(context.applicationContext, myCustomHttpStack)
*/
class UserApi (
private val context: Context,
private val requestQueue: Lazy<RequestQueue> = lazy(initializer = {
Volley.newRequestQueue(context.applicationContext)
}),
private val requestFactory: IRequestFactory = RequestFactory(),
private val basePath: String = "http://petstore.swagger.io/v2",
private val postProcessors :List <(Request<*>) -> Unit> = listOf()) {
/**
* Create user
* This can only be done by the logged in user.
* @param body Created user object
* @return void
*/
suspend fun createUser(body: User): Unit {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Creates list of users with given input array
*
* @param body List of user object
* @return void
*/
suspend fun createUsersWithArrayInput(body: kotlin.collections.List<User>): Unit {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/createWithArray";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Creates list of users with given input array
*
* @param body List of user object
* @return void
*/
suspend fun createUsersWithListInput(body: kotlin.collections.List<User>): Unit {
val body: Any? = body
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/createWithList";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.POST,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Delete user
* This can only be done by the logged in user.
* @param username The name that needs to be deleted
* @return void
*/
suspend fun deleteUser(username: kotlin.String): Unit {
val body: Any? = null
// verify the required parameter 'username' is set
// This is probably taken care of by non-null types anyway
requireNotNull(username)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/{username}".replace("{" + "username" + "}", IRequestFactory.escapeString(username.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.DELETE,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Get user by user name
*
* @param username The name that needs to be fetched. Use user1 for testing.
* @return User
*/
suspend fun getUserByName(username: kotlin.String): User? {
val body: Any? = null
// verify the required parameter 'username' is set
// This is probably taken care of by non-null types anyway
requireNotNull(username)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/{username}".replace("{" + "username" + "}", IRequestFactory.escapeString(username.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<User> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<User>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<User> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Logs user into the system
*
* @param username The user name for login
* @param password The password for login in clear text
* @return kotlin.String
*/
suspend fun loginUser(username: kotlin.String, password: kotlin.String): kotlin.String? {
val body: Any? = null
// verify the required parameter 'username' is set
// This is probably taken care of by non-null types anyway
requireNotNull(username)
// verify the required parameter 'password' is set
// This is probably taken care of by non-null types anyway
requireNotNull(password)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/login";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
"username" to IRequestFactory.parameterToString(username),
"password" to IRequestFactory.parameterToString(password),
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<kotlin.String> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<kotlin.String>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<kotlin.String> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* Logs out current logged in user session
*
* @return void
*/
suspend fun logoutUser(): Unit {
val body: Any? = null
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/logout";
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.GET,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
/**
* 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
*/
suspend fun updateUser(username: kotlin.String, body: User): Unit {
val body: Any? = body
// verify the required parameter 'username' is set
// This is probably taken care of by non-null types anyway
requireNotNull(username)
// verify the required parameter 'body' is set
// This is probably taken care of by non-null types anyway
requireNotNull(body)
val contentTypes : Array<String> = arrayOf()
val contentType: String = if (contentTypes.isNotEmpty()) { contentTypes.first() } else { "application/json" }
// Do some work or avoid some work based on what we know about the model,
// before we delegate to a pluggable request factory template
// The request factory template contains only pure code and no templates
// to make it easy to override with your own.
// create path and map variables
val path = "/user/{username}".replace("{" + "username" + "}", IRequestFactory.escapeString(username.toString()));
// form params
val formParams = mapOf<String, String>(
)
// TODO: Cater for allowing empty values
// TODO, if its apikey auth, then add the header names here and the hardcoded auth key
// Only support hard coded apikey in query param auth for when we do this first path
val queryParams = mapOf<String, String>(
).filter { it.value.isNotEmpty() }
val headerParams: Map<String, String> = mapOf(
)
return suspendCoroutine { continuation ->
val responseListener = Response.Listener<Unit> { response ->
continuation.resume(response)
}
val errorListener = Response.ErrorListener { error ->
continuation.resumeWithException(error)
}
val responseType = object : TypeToken<Unit>() {}.type
// Call the correct request builder based on whether we have a return type or a body.
// All other switching on types must be done in code inside the builder
val request: Request<Unit> = requestFactory.build(
Request.Method.PUT,
"$basePath$path",
body,
headerParams,
queryParams,
formParams,
contentType,
responseType,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
requestQueue.value.add(request)
}
}
}

View File

@ -0,0 +1,33 @@
package org.openapitools.client.infrastructure
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.google.gson.stream.JsonToken.NULL
import java.io.IOException
class ByteArrayAdapter : TypeAdapter<ByteArray>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: ByteArray?) {
if (value == null) {
out?.nullValue()
} else {
out?.value(String(value))
}
}
@Throws(IOException::class)
override fun read(out: JsonReader?): ByteArray? {
out ?: return null
when (out.peek()) {
NULL -> {
out.nextNull()
return null
}
else -> {
return out.nextString().toByteArray()
}
}
}
}

View File

@ -0,0 +1,56 @@
package org.openapitools.client.infrastructure
class CollectionFormats {
open class CSVParams {
var params: List<String>
constructor(params: List<String>) {
this.params = params
}
constructor(vararg params: String) {
this.params = listOf(*params)
}
override fun toString(): String {
return params.joinToString(",")
}
}
open class SSVParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString(" ")
}
}
class TSVParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString("\t")
}
}
class PIPESParams : CSVParams {
constructor(params: List<String>) : super(params)
constructor(vararg params: String) : super(*params)
override fun toString(): String {
return params.joinToString("|")
}
}
class SPACEParams : SSVParams()
}

View File

@ -0,0 +1,28 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.infrastructure
import org.openapitools.client.models.room.*
// TODO ITransformForStorage
interface ITransformForStorage<T> {
fun toRoomModel(): T
}

View File

@ -0,0 +1,35 @@
package org.openapitools.client.infrastructure
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.google.gson.stream.JsonToken.NULL
import java.io.IOException
import java.time.LocalDate
import java.time.format.DateTimeFormatter
class LocalDateAdapter(private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE) : TypeAdapter<LocalDate>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: LocalDate?) {
if (value == null) {
out?.nullValue()
} else {
out?.value(formatter.format(value))
}
}
@Throws(IOException::class)
override fun read(out: JsonReader?): LocalDate? {
out ?: return null
when (out.peek()) {
NULL -> {
out.nextNull()
return null
}
else -> {
return LocalDate.parse(out.nextString(), formatter)
}
}
}
}

View File

@ -0,0 +1,35 @@
package org.openapitools.client.infrastructure
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.google.gson.stream.JsonToken.NULL
import java.io.IOException
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class LocalDateTimeAdapter(private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME) : TypeAdapter<LocalDateTime>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: LocalDateTime?) {
if (value == null) {
out?.nullValue()
} else {
out?.value(formatter.format(value))
}
}
@Throws(IOException::class)
override fun read(out: JsonReader?): LocalDateTime? {
out ?: return null
when (out.peek()) {
NULL -> {
out.nextNull()
return null
}
else -> {
return LocalDateTime.parse(out.nextString(), formatter)
}
}
}
}

View File

@ -0,0 +1,35 @@
package org.openapitools.client.infrastructure
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import com.google.gson.stream.JsonToken.NULL
import java.io.IOException
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
class OffsetDateTimeAdapter(private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME) : TypeAdapter<OffsetDateTime>() {
@Throws(IOException::class)
override fun write(out: JsonWriter?, value: OffsetDateTime?) {
if (value == null) {
out?.nullValue()
} else {
out?.value(formatter.format(value))
}
}
@Throws(IOException::class)
override fun read(out: JsonReader?): OffsetDateTime? {
out ?: return null
when (out.peek()) {
NULL -> {
out.nextNull()
return null
}
else -> {
return OffsetDateTime.parse(out.nextString(), formatter)
}
}
}
}

View File

@ -0,0 +1,57 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.ApiResponseRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* Describes the result of uploading an image resource
*
* @param code
* @param type
* @param message
*/
data class ApiResponse (
@SerializedName("code")
val code: kotlin.Int? = null,
@SerializedName("type")
val type: kotlin.String? = null,
@SerializedName("message")
val message: kotlin.String? = null
): ITransformForStorage<ApiResponseRoomModel> {
companion object { }
override fun toRoomModel(): ApiResponseRoomModel =
ApiResponseRoomModel(roomTableId = 0,
code = this.code,
type = this.type,
message = this.message,
)
}

View File

@ -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.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.CategoryRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* A category for a pet
*
* @param id
* @param name
*/
data class Category (
@SerializedName("id")
val id: kotlin.Long? = null,
@SerializedName("name")
val name: kotlin.String? = null
): ITransformForStorage<CategoryRoomModel> {
companion object { }
override fun toRoomModel(): CategoryRoomModel =
CategoryRoomModel(roomTableId = 0,
id = this.id,
name = this.name,
)
}

View File

@ -0,0 +1,57 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.ModelApiResponseRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* Describes the result of uploading an image resource
*
* @param code
* @param type
* @param message
*/
data class ModelApiResponse (
@SerializedName("code")
val code: kotlin.Int? = null,
@SerializedName("type")
val type: kotlin.String? = null,
@SerializedName("message")
val message: kotlin.String? = null
): ITransformForStorage<ModelApiResponseRoomModel> {
companion object { }
override fun toRoomModel(): ModelApiResponseRoomModel =
ModelApiResponseRoomModel(roomTableId = 0,
code = this.code,
type = this.type,
message = this.message,
)
}

View File

@ -0,0 +1,83 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.OrderRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* 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 (
@SerializedName("id")
val id: kotlin.Long? = null,
@SerializedName("petId")
val petId: kotlin.Long? = null,
@SerializedName("quantity")
val quantity: kotlin.Int? = null,
@SerializedName("shipDate")
val shipDate: java.time.OffsetDateTime? = null,
/* Order Status */
@SerializedName("status")
val status: Order.Status? = null,
@SerializedName("complete")
val complete: kotlin.Boolean? = false
): ITransformForStorage<OrderRoomModel> {
companion object { }
override fun toRoomModel(): OrderRoomModel =
OrderRoomModel(roomTableId = 0,
id = this.id,
petId = this.petId,
quantity = this.quantity,
shipDate = this.shipDate,
status = this.status,
complete = this.complete,
)
/**
* Order Status
*
* Values: placed,approved,delivered
*/
enum class Status(val value: kotlin.String) {
@SerializedName(value = "placed") placed("placed"),
@SerializedName(value = "approved") approved("approved"),
@SerializedName(value = "delivered") delivered("delivered");
}
}

View File

@ -0,0 +1,85 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import org.openapitools.client.models.Category
import org.openapitools.client.models.Tag
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.PetRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* A pet for sale in the pet store
*
* @param name
* @param photoUrls
* @param id
* @param category
* @param tags
* @param status pet status in the store
*/
data class Pet (
@SerializedName("name")
val name: kotlin.String,
@SerializedName("photoUrls")
val photoUrls: kotlin.collections.List<kotlin.String>,
@SerializedName("id")
val id: kotlin.Long? = null,
@SerializedName("category")
val category: Category? = null,
@SerializedName("tags")
val tags: kotlin.collections.List<Tag>? = null,
/* pet status in the store */
@SerializedName("status")
val status: Pet.Status? = null
): ITransformForStorage<PetRoomModel> {
companion object { }
override fun toRoomModel(): PetRoomModel =
PetRoomModel(roomTableId = 0,
name = this.name,
photoUrls = this.photoUrls,
id = this.id,
category = this.category,
status = this.status,
)
/**
* pet status in the store
*
* Values: available,pending,sold
*/
enum class Status(val value: kotlin.String) {
@SerializedName(value = "available") available("available"),
@SerializedName(value = "pending") pending("pending"),
@SerializedName(value = "sold") sold("sold");
}
}

View File

@ -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.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.TagRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* A tag for a pet
*
* @param id
* @param name
*/
data class Tag (
@SerializedName("id")
val id: kotlin.Long? = null,
@SerializedName("name")
val name: kotlin.String? = null
): ITransformForStorage<TagRoomModel> {
companion object { }
override fun toRoomModel(): TagRoomModel =
TagRoomModel(roomTableId = 0,
id = this.id,
name = this.name,
)
}

View File

@ -0,0 +1,83 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models
import com.google.gson.annotations.SerializedName
import org.openapitools.client.models.room.UserRoomModel
import org.openapitools.client.infrastructure.ITransformForStorage
/**
* 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 (
@SerializedName("id")
val id: kotlin.Long? = null,
@SerializedName("username")
val username: kotlin.String? = null,
@SerializedName("firstName")
val firstName: kotlin.String? = null,
@SerializedName("lastName")
val lastName: kotlin.String? = null,
@SerializedName("email")
val email: kotlin.String? = null,
@SerializedName("password")
val password: kotlin.String? = null,
@SerializedName("phone")
val phone: kotlin.String? = null,
/* User Status */
@SerializedName("userStatus")
val userStatus: kotlin.Int? = null
): ITransformForStorage<UserRoomModel> {
companion object { }
override fun toRoomModel(): UserRoomModel =
UserRoomModel(roomTableId = 0,
id = this.id,
username = this.username,
firstName = this.firstName,
lastName = this.lastName,
email = this.email,
password = this.password,
phone = this.phone,
userStatus = this.userStatus,
)
}

View File

@ -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.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "ApiResponse")
/**
* Room model for Describes the result of uploading an image resource
* @param code
* @param type
* @param message
*/
data class ApiResponseRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var code: kotlin.Int? = null,
var type: kotlin.String? = null,
var message: kotlin.String? = null,
) {
companion object { }
fun toApiModel(): ApiResponse = ApiResponse(
code = this.code,
type = this.type,
message = this.message,
)
}

View File

@ -0,0 +1,49 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "Category")
/**
* Room model for A category for a pet
* @param id
* @param name
*/
data class CategoryRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var id: kotlin.Long? = null,
var name: kotlin.String? = null,
) {
companion object { }
fun toApiModel(): Category = Category(
id = this.id,
name = this.name,
)
}

View File

@ -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.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "ModelApiResponse")
/**
* Room model for Describes the result of uploading an image resource
* @param code
* @param type
* @param message
*/
data class ModelApiResponseRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var code: kotlin.Int? = null,
var type: kotlin.String? = null,
var message: kotlin.String? = null,
) {
companion object { }
fun toApiModel(): ModelApiResponse = ModelApiResponse(
code = this.code,
type = this.type,
message = this.message,
)
}

View File

@ -0,0 +1,61 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "Order")
/**
* Room model for 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 OrderRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var id: kotlin.Long? = null,
var petId: kotlin.Long? = null,
var quantity: kotlin.Int? = null,
var shipDate: java.time.OffsetDateTime? = null,
var complete: kotlin.Boolean? = null,
var status: Order.Status? = null,
) {
companion object { }
fun toApiModel(): Order = Order(
id = this.id,
petId = this.petId,
quantity = this.quantity,
shipDate = this.shipDate,
status = this.status,
complete = this.complete,
)
}

View File

@ -0,0 +1,63 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "Pet")
/**
* Room model for A pet for sale in the pet store
* @param name
* @param photoUrls
* @param id
* @param category
* @param tags
* @param status pet status in the store
*/
data class PetRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var photoUrls: kotlin.collections.List<kotlin.String>,
var name: kotlin.String,
var id: kotlin.Long? = null,
var category: Category? = null,
var status: Pet.Status? = null,
) {
@Ignore
var tags: kotlin.collections.List<Tag>? = null
companion object { }
fun toApiModel(): Pet = Pet(
name = this.name,
photoUrls = this.photoUrls,
id = this.id,
category = this.category,
tags = this.tags,
status = this.status,
)
}

View File

@ -0,0 +1,49 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "Tag")
/**
* Room model for A tag for a pet
* @param id
* @param name
*/
data class TagRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var id: kotlin.Long? = null,
var name: kotlin.String? = null,
) {
companion object { }
fun toApiModel(): Tag = Tag(
id = this.id,
name = this.name,
)
}

View File

@ -0,0 +1,67 @@
/**
* OpenAPI Petstore
*
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* Please note:
* This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* Do not edit this file manually.
*/
@file:Suppress(
"ArrayInDataClass",
"EnumEntryName",
"RemoveRedundantQualifierName",
"UnusedImport"
)
package org.openapitools.client.models.room
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.openapitools.client.models.*
@Entity(tableName = "User")
/**
* Room model for 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 UserRoomModel (
@PrimaryKey(autoGenerate = true) var roomTableId: Int,
var id: kotlin.Long? = null,
var username: kotlin.String? = null,
var firstName: kotlin.String? = null,
var lastName: kotlin.String? = null,
var email: kotlin.String? = null,
var password: kotlin.String? = null,
var phone: kotlin.String? = null,
var userStatus: kotlin.Int? = null,
) {
companion object { }
fun toApiModel(): User = User(
id = this.id,
username = this.username,
firstName = this.firstName,
lastName = this.lastName,
email = this.email,
password = this.password,
phone = this.phone,
userStatus = this.userStatus,
)
}

View File

@ -0,0 +1,119 @@
package org.openapitools.client.request
import com.android.volley.NetworkResponse
import com.android.volley.ParseError
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.HttpHeaderParser
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.net.HttpURLConnection
import java.lang.reflect.Type
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.OffsetDateTime
import org.openapitools.client.infrastructure.OffsetDateTimeAdapter
import org.openapitools.client.infrastructure.LocalDateTimeAdapter
import org.openapitools.client.infrastructure.LocalDateAdapter
import org.openapitools.client.infrastructure.ByteArrayAdapter
class GsonRequest<T>(
method: Int,
url: String,
private val body: Any?,
private val headers: Map<String, String>?,
private val params: MutableMap<String, String>?,
private val contentTypeForBody: String?,
private val encodingForParams: String?,
private val gsonAdapters: Map<Type, Any>?,
private val type: Type,
private val listener: Response.Listener<T>,
errorListener: Response.ErrorListener
) : Request<T>(method, url, errorListener) {
val gsonBuilder: GsonBuilder = GsonBuilder()
.registerTypeAdapter(OffsetDateTime::class.java, OffsetDateTimeAdapter())
.registerTypeAdapter(LocalDateTime::class.java, LocalDateTimeAdapter())
.registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
.registerTypeAdapter(ByteArray::class.java, ByteArrayAdapter())
.apply {
gsonAdapters?.forEach {
this.registerTypeAdapter(it.key, it.value)
}
}
val gson: Gson by lazy {
gsonBuilder.create()
}
private var response: NetworkResponse? = null
override fun deliverResponse(response: T?) {
listener.onResponse(response)
}
override fun getParams(): MutableMap<String, String>? = params ?: super.getParams()
override fun getBodyContentType(): String = contentTypeForBody ?: super.getBodyContentType()
override fun getParamsEncoding(): String = encodingForParams ?: super.getParamsEncoding()
override fun getHeaders(): MutableMap<String, String> {
val combined = HashMap<String, String>()
combined.putAll(super.getHeaders())
if (headers != null) {
combined.putAll(headers)
}
return combined
}
override fun getBody(): ByteArray? {
if (body != null) {
return gson.toJson(body).toByteArray(Charsets.UTF_8)
}
return super.getBody()
}
override fun parseNetworkResponse(response: NetworkResponse?): Response<T> {
return try {
this.response = copyTo(response)
val json = String(
response?.data ?: ByteArray(0),
Charset.forName(HttpHeaderParser.parseCharset(response?.headers))
)
Response.success(
gson.fromJson<T>(json, type),
HttpHeaderParser.parseCacheHeaders(response)
)
} catch (e: UnsupportedEncodingException) {
Response.error(ParseError(e))
} catch (e: JsonSyntaxException) {
Response.error(ParseError(e))
}
}
private fun copyTo(response: NetworkResponse?): NetworkResponse {
return if (response != null) {
NetworkResponse(
response.statusCode,
response.data,
response.notModified,
response.networkTimeMs,
response.allHeaders
)
} else {
// Return an empty response.
NetworkResponse(
HttpURLConnection.HTTP_BAD_METHOD,
ByteArray(0),
false,
0,
emptyList()
)
}
}
}

View File

@ -0,0 +1,64 @@
package org.openapitools.client.request
import com.android.volley.Request
import com.android.volley.Response
import java.io.UnsupportedEncodingException
import java.lang.reflect.Type
import java.net.URLEncoder
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.time.format.DateTimeFormatter
import java.time.OffsetDateTime
import java.time.LocalDate
interface IRequestFactory {
companion object {
/**
* ISO 8601 date time format.
* @see https://en.wikipedia.org/wiki/ISO_8601
*/
fun formatDateTime(datetime: OffsetDateTime) = DateTimeFormatter.ISO_INSTANT.format(datetime)
fun formatDate(date: LocalDate) = DateTimeFormatter.ISO_LOCAL_DATE.format(date)
fun escapeString(str: String): String {
return try {
URLEncoder.encode(str, "UTF-8")
} catch (e: UnsupportedEncodingException) {
str
}
}
fun parameterToString(param: Any?) =
when (param) {
null -> ""
is OffsetDateTime -> formatDateTime(param)
is Collection<*> -> {
val b = StringBuilder()
for (o in param) {
if (b.isNotEmpty()) {
b.append(",")
}
b.append(o.toString())
}
b.toString()
}
else -> param.toString()
}
}
fun <T> build(
method: Int,
url : String,
body: Any?,
headers: Map<String, String>?,
queryParams: Map<String, String>?,
formParams: Map<String, String>?,
contentTypeForBody: String?,
type: Type,
responseListener: Response.Listener<T>,
errorListener: Response.ErrorListener): Request<T>
}

View File

@ -0,0 +1,87 @@
// Knowing the details of an operation it will produce a call to a Volley Request constructor
package org.openapitools.client.request
import com.android.volley.Request
import com.android.volley.Response
import android.util.Base64
import org.openapitools.client.request.IRequestFactory.Companion.escapeString
import java.lang.reflect.Type
import java.util.Locale
import java.util.UUID
class RequestFactory(private val headerFactories : List<() -> Map<String, String>> = listOf(), private val postProcessors :List <(Request<*>) -> Unit> = listOf(), private val gsonAdapters: Map<Type, Any> = mapOf()): IRequestFactory {
companion object Authentication {
// Where a header factory requires parameters a client will need to bind these
// TODO Generate appropriate header factories based on settings
// Api Key auth supports query header and cookie.
// Query is supported in the path generation only with a hardcoded value.
// TODO: Not sure about cookie auth form
// If implementing api key in query parameter use the ^isKeyInHeader property
val apiKeyAuthHeaderFactoryBuilder = {
paramName: String, apiKeyPrefix: String?, apiKey: String? -> {
mapOf(paramName to
if (apiKeyPrefix != null) {
"$apiKeyPrefix $apiKey"
} else {
apiKey!!
}
)
}
}
// TODO: Oauth not implemented yet - comment out below as OAuth does not exist
}
/**
* {@inheritDoc}
*/
@Suppress("UNCHECKED_CAST")
override fun <T> build(
method: Int,
url: String,
body: Any?,
headers: Map<String, String>?,
queryParams: Map<String, String>?,
formParams: Map<String, String>?,
contentTypeForBody: String?,
type: Type,
responseListener: Response.Listener<T>,
errorListener: Response.ErrorListener
): Request<T> {
val afterMarketHeaders = (headers?.toMutableMap() ?: mutableMapOf())
// Factory built and aftermarket
// Merge the after market headers on top of the base ones in case we are overriding per call auth
val allHeaders = headerFactories.fold(afterMarketHeaders) { acc, factory -> (acc + factory.invoke()).toMutableMap() }
// If we decide to support auth parameters in the url, then you will reference them by supplying a url string
// with known variable name refernces in the string. We will then apply
val updatedUrl = if (!queryParams.isNullOrEmpty()) {
queryParams.asSequence().fold("$url?") {acc, param ->
"$acc${escapeString(param.key)}=${escapeString(param.value)}&"
}.trimEnd('&')
} else {
url
}
val request = GsonRequest(
method,
updatedUrl,
body,
allHeaders,
formParams?.toMutableMap(),
contentTypeForBody,
null,
gsonAdapters,
type,
responseListener,
errorListener)
postProcessors.forEach{ it.invoke(request)}
return request
}
}