* Add AuthorizationInterceptor template

* Add JsonAdapters templates for models with DateTime fields
This commit is contained in:
AnastasiyaK97 2022-08-22 21:25:29 +03:00 committed by Anastasiya97
parent a61db49a96
commit bb2cc46699
12 changed files with 198 additions and 88 deletions

View File

@ -6,6 +6,9 @@ import io.swagger.codegen.v3.*;
import io.swagger.codegen.v3.generators.handlebars.BaseItemsHelper;
import io.swagger.codegen.v3.generators.handlebars.ExtensionHelper;
import io.swagger.codegen.v3.generators.kotlin.AbstractKotlinCodegen;
import io.swagger.v3.oas.models.media.DateSchema;
import io.swagger.v3.oas.models.media.DateTimeSchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -22,8 +25,8 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
protected String dateLibrary = DateLibrary.JODA_TIME.value;
protected String projectName = "SwaggerAPI";
private Map<String, String> allCustomDateFormats = new HashMap<>();
private Set<String> allEnumAdapters = new HashSet<>();
private Set<String> allEnumAdaptersImports = new HashSet<>();
private Set<String> allJsonAdapters = new HashSet<>();
private Set<String> allJsonAdaptersImports = new HashSet<>();
public enum DateLibrary {
STRING("string"),
@ -94,12 +97,12 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
supportingFiles.add(new SupportingFile("APIDateFormat.mustache",
sourceFolder,
"APIDateFormat.kt"));
supportingFiles.add(new SupportingFile("GeneratedDateAdapter.mustache",
supportingFiles.add(new SupportingFile("JsonAdapters.mustache",
sourceFolder,
"GeneratedDateAdapter.kt"));
supportingFiles.add(new SupportingFile("EnumJsonAdapters.mustache",
"JsonAdapters.kt"));
supportingFiles.add(new SupportingFile("AuthorizationInterceptor.mustache",
sourceFolder,
"EnumJsonAdapters.kt"));
"AuthorizationInterceptor.kt"));
return supportingFiles;
}
@ -152,8 +155,8 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
Map<String, Object> supportingFileData = super.postProcessSupportingFileData(objs);
supportingFileData.put("apiDateFormats", allCustomDateFormats);
supportingFileData.put("enumAdapters", allEnumAdapters);
supportingFileData.put("enumAdaptersImports", allEnumAdaptersImports);
supportingFileData.put("jsonAdapters", allJsonAdapters);
supportingFileData.put("jsonAdaptersImports", allJsonAdaptersImports);
return supportingFileData;
}
@ -161,32 +164,51 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
updateEnumAdapters(model, property);
if (typeAliases.containsKey(property.baseType)) {
Schema resolvedPropertySchema = getOpenAPI().getComponents().getSchemas().get(property.datatype);
postProcessAliasProperty(property, resolvedPropertySchema);
}
addEnumJsonAdapters(model, property);
updateVendorExtensionsForProperty(property);
if (property.getIsListContainer()) {
updateVendorExtensionsForProperty(property.items);
}
if (isDateFormatProperty(property)) {
model.getVendorExtensions().put(TINetworkingCodegenConstants.HAS_DATE, Boolean.TRUE);
addJsonAdaptersForModelWithDate(model);
}
if (property.getIsObject() && isReservedWord(property.getDatatype())) {
property.datatype = escapeReservedTypeDeclaration(property.getDatatype());
property.datatypeWithEnum = property.datatype;
}
}
private void updateEnumAdapters(CodegenModel model, CodegenProperty property) {
private void addEnumJsonAdapters(CodegenModel model, CodegenProperty property) {
boolean isEnum = ExtensionHelper.getBooleanValue(property, "x-is-enum");
if (isEnum) {
String enumAdapterName = model.name + "." + property.enumName + ".JsonAdapter";
String importName = modelPackage + "." + model.name;
allEnumAdapters.add(enumAdapterName);
allEnumAdaptersImports.add(importName);
allJsonAdapters.add(enumAdapterName);
allJsonAdaptersImports.add(importName);
}
}
private void addJsonAdaptersForModelWithDate(CodegenModel model) {
String jsonAdapterName = model.name + "." + model.name + "JsonAdapter";
String importName = modelPackage + "." + model.name;
allJsonAdapters.add(jsonAdapterName);
allJsonAdaptersImports.add(importName);
}
@Override
public String toParamName(String name) {
return super.toParamName(name).replaceAll("[^A-Za-z0-9_]", "");
return replaceSpecialCharacters(super.toParamName(name));
}
@Override
@ -216,16 +238,21 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
if (isISO8601DateProperty(property)) {
vendorExtensions.put(TINetworkingCodegenConstants.IS_ISO8601_DATE, true);
vendorExtensions.put(TINetworkingCodegenConstants.IS_DATE_FORMAT, true);
} else if (isCustomDateFormatProperty(property)) {
String customDateFormat = (String) vendorExtensions.get(TINetworkingCodegenConstants.DATE_FORMAT);
String dateFormatName = customDateFormat.replace(".", "_")
.replaceAll("[^A-Za-z0-9_]", "");
String dateFormatName = replaceSpecialCharacters(customDateFormat.replace(".", "_"));
vendorExtensions.put(TINetworkingCodegenConstants.DATE_FORMAT_NAME, dateFormatName);
vendorExtensions.put(TINetworkingCodegenConstants.IS_DATE_FORMAT, true);
allCustomDateFormats.put(dateFormatName, customDateFormat);
}
}
private String replaceSpecialCharacters(String text) {
return text.replaceAll("[^A-Za-z0-9_]", "");
}
private boolean isISO8601DateProperty(CodegenProperty property) {
return property.getIsDate()
|| property.getIsDateTime()
@ -235,4 +262,33 @@ public class TINetworkingCodegen extends AbstractKotlinCodegen {
private boolean isCustomDateFormatProperty(CodegenProperty property) {
return property.getVendorExtensions().containsKey(TINetworkingCodegenConstants.DATE_FORMAT);
}
private boolean isDateFormatProperty(CodegenProperty property) {
Map<String, Object> vendorExtensions = property.getVendorExtensions();
return vendorExtensions.containsKey(TINetworkingCodegenConstants.DATE_FORMAT)
|| property.getIsDate()
|| property.getIsDateTime();
}
private void postProcessAliasProperty(CodegenProperty codegenProperty, Schema resolvedPropertySchema) {
Map<String, Object> propertyExtensions = codegenProperty.getVendorExtensions();
propertyExtensions.put(CodegenConstants.IS_ALIAS_EXT_NAME, Boolean.TRUE);
codegenProperty.setDescription(codegenProperty.getDescription() == null
? resolvedPropertySchema.getDescription()
: codegenProperty.getDescription());
if (resolvedPropertySchema.getExtensions() != null) {
propertyExtensions.putAll(resolvedPropertySchema.getExtensions());
}
if (resolvedPropertySchema instanceof DateSchema) {
propertyExtensions.put(CodegenConstants.IS_DATE_EXT_NAME, Boolean.TRUE);
}
if (resolvedPropertySchema instanceof DateTimeSchema) {
propertyExtensions.put(CodegenConstants.IS_DATE_TIME_EXT_NAME, Boolean.TRUE);
}
}
}

View File

@ -4,4 +4,6 @@ public class TINetworkingCodegenConstants {
public static final String DATE_FORMAT = "x-custom-date-format";
public static final String DATE_FORMAT_NAME = "x-codegen-date-format-name";
public static final String IS_ISO8601_DATE = "x-codegen-is-iso8601-date";
public static final String HAS_DATE = "x-has-date";
public static final String IS_DATE_FORMAT = "x-is-date-format";
}

View File

@ -1,36 +1,44 @@
{{>licenseInfo}}
package {{packageName}}
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
/**
* Util object for handling some cases with DateTime e.g. parsing string to DateTime object
*/
* Util object for handling some cases with DateTime e.g. parsing string to DateTime object
*/
object DateFormatUtils {
enum class APIDateFormat(val formatValue: String) {
DATE_TIME_FORMAT("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"),
DATE_FORMAT("yyyy-MM-dd"),
TIME_FORMAT("HH:mm:ssZ"),
DATE_TIME_FORMAT("yyyy-MM-dd'T'HH:mm:ss.SSSZZ"),
DATE_FORMAT("yyyy-MM-dd"),
TIME_FORMAT("HH:mm:ssZ"),
{{#each apiDateFormats as |value key|}}
{{key}}("{{{value}}}")
{{key}}("{{{value}}}")
{{/each}}
}
/**
* @return the result of parsed string value
* @param value is string value of date time in right format
* @param format is date time format for parsing string value.
* Default value is [Format.DATE_TIME_FORMAT]
* @param defaultValue is value returned in case of exception
*/
* @return the result of parsed string value
* @param value is string value of date time in right format
* @param format is date time format for parsing string value.
* Default value is [Format.DATE_TIME_FORMAT]
* @param defaultValue is value returned in case of exception
*/
fun fromString(
value: String,
format: APIDateFormat = APIDateFormat.DATE_TIME_FORMAT,
defaultValue: DateTime? = null
): DateTime? = runCatching { value.parse(format.formatValue) }.getOrDefault(defaultValue)
value: String?,
format: APIDateFormat = APIDateFormat.DATE_TIME_FORMAT,
defaultValue: DateTime? = null
): DateTime? = value?.let {
runCatching { value.parse(format.formatValue) }.getOrDefault(defaultValue)
}
private fun String.parse(format: String) = DateTimeFormat.forPattern(format).parseDateTime(this)
fun toString(
value: DateTime?,
format: APIDateFormat = APIDateFormat.DATE_TIME_FORMAT
): String = value?.toString(DateTimeFormat.forPattern(format.formatValue)) ?: ""
}

View File

@ -0,0 +1,38 @@
{{>licenseInfo}}
package {{packageName}}
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import retrofit2.Invocation
import java.io.IOException
class AuthorizationInterceptor : Interceptor {
private var sessionToken: String? = null
fun setSessionToken(sessionToken: String?) {
this.sessionToken = sessionToken
}
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request: Request = chain.request()
val requestBuilder: Request.Builder = request.newBuilder()
if (request.needAuth()) {
{{#authMethods}}
{{#isApiKey}}{{#isKeyInHeader}}requestBuilder.addHeader("{{keyParamName}}", sessionToken){{/isKeyInHeader}}{{/isApiKey}}
{{/authMethods}}
}
return chain.proceed(requestBuilder.build())
}
}
fun Request.needAuth() = tag(Invocation::class.java)?.method()?.getAnnotation(AuthRequest::class.java) != null
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class AuthRequest()

View File

@ -1,13 +0,0 @@
{{>licenseInfo}}
package {{packageName}}
import com.squareup.moshi.Moshi
{{#each enumAdaptersImports}}
import {{.}}
{{/each}}
fun Moshi.Builder.addGeneratedEnumJsonAdapters(): Moshi.Builder = this
.add(GeneratedDateAdapter())
{{#each enumAdapters}}
.add({{.}}())
{{/each}}

View File

@ -1,32 +0,0 @@
{{>licenseInfo}}
package {{packageName}}
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.ToJson
import org.joda.time.DateTime
import {{packageName}}.DateFormatUtils.APIDateFormat
class GeneratedDateAdapter : JsonAdapter<DateTime>() {
@FromJson
override fun fromJson(reader: JsonReader): DateTime? {
val dateAsString = reader.nextString()
val date = DateFormatUtils.fromString(value = dateAsString, format = APIDateFormat.DATE_TIME_FORMAT)
?: DateFormatUtils.fromString(value = dateAsString, format = APIDateFormat.DATE_FORMAT)
?: DateFormatUtils.fromString(value = dateAsString, format = APIDateFormat.TIME_FORMAT)
{{#each apiDateFormats as |value key|}}
?: DateFormatUtils.fromString(value = dateAsString, format = APIDateFormat.{{key}})
{{/each}}
return date
}
@ToJson
override fun toJson(writer: JsonWriter, value: DateTime?) {
if (value != null) {
writer.value(value.toString())
}
}
}

View File

@ -0,0 +1,13 @@
{{>licenseInfo}}
package {{packageName}}
import com.squareup.moshi.Moshi
{{#each jsonAdaptersImports}}
import {{.}}
{{/each}}
fun Moshi.Builder.addGeneratedJsonAdapters(): Moshi.Builder = this
{{#each jsonAdapters}}
.add({{.}}())
{{/each}}

View File

@ -1,4 +1,5 @@
{{>licenseInfo}}
package {{apiPackage}}
import retrofit2.http.DELETE
@ -6,6 +7,7 @@ import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.PUT
import {{packageName}}.AuthRequest
{{#imports}}import {{import}}
{{/imports}}
{{#jodaTime}}
@ -23,10 +25,10 @@ interface {{classname}} {
{{/parameters}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
*/{{#returnType}}
{{/returnType}}
{{#if authMethods}}@AuthRequest{{/if}}
@{{httpMethod}}("{{{path}}}")
suspend fun {{operationId}}({{#parameters}}
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{#hasMore}},{{/hasMore}}{{/parameters}}{{#if authMethods}}{{#if parameters}},
{{/if}}{{/if}}{{#authMethods}}{{>securityParam}}{{#hasMore}},{{/hasMore}}{{/authMethods}}
{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{#hasMore}},{{/hasMore}}{{/parameters}}
): {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Unit{{/returnType}}
{{/contents}}

View File

@ -4,18 +4,56 @@
* @param {{name}} {{{description}}}
{{/allVars}}
*/
{{#if vendorExtensions.x-has-date}}
{{else}}
@JsonClass(generateAdapter = true)
{{/if}}
{{#hasVars}}data {{/hasVars}}class {{classname}} (
{{#allVars}}
{{#required}}{{>data_class_req_var}}{{^@last}},{{/@last}}{{/required}}{{^required}}{{>data_class_opt_var}}{{^@last}},{{/@last}}{{/required}}
{{/allVars}}
) {
{{#if vendorExtensions.x-has-date}}
@JsonClass(generateAdapter = true)
data class {{classname}}Json(
{{#allVars}}
{{#required}}{{>data_class_req_var_adapter}}{{^@last}},{{/@last}}{{/required}}{{^required}}{{>data_class_opt_var_adapter}}{{^@last}},{{/@last}}{{/required}}
{{/allVars}}
)
class {{classname}}JsonAdapter() {
@FromJson
fun fromJson(json: {{classname}}Json): {{classname}} {
return {{classname}}(
{{#allVars}}
{{{name}}} = {{#if vendorExtensions.x-is-date-format}}{{packageName}}.DateFormatUtils.fromString(
value = json.{{{name}}},
format = {{packageName}}.DateFormatUtils.APIDateFormat.{{#if vendorExtensions.x-codegen-is-iso8601-date}}{{#isDate}}DATE_FORMAT{{/isDate}}{{#isDateTime}}DATE_TIME_FORMAT{{/isDateTime}}{{else if vendorExtensions.x-custom-date-format}}{{vendorExtensions.x-codegen-date-format-name}}{{/if}}
){{#required}} ?: throw com.squareup.moshi.JsonDataException("Non-null value '{{{name}}}' was null at {{classname}}"){{/required}}{{else}}json.{{{name}}}{{/if}}{{^@last}},{{/@last}}
{{/allVars}}
)
}
@ToJson
fun toJson(model: {{classname}}): {{classname}}Json {
return {{classname}}Json(
{{#allVars}}
{{{name}}} = {{#if vendorExtensions.x-is-date-format}}{{packageName}}.DateFormatUtils.toString(
value = model.{{{name}}},
format = {{packageName}}.DateFormatUtils.APIDateFormat.{{#if vendorExtensions.x-codegen-is-iso8601-date}}{{#isDate}}DATE_FORMAT{{/isDate}}{{#isDateTime}}DATE_TIME_FORMAT{{/isDateTime}}{{else if vendorExtensions.x-custom-date-format}}{{vendorExtensions.x-codegen-date-format-name}}{{/if}}
){{else}}model.{{{name}}}{{/if}}{{^@last}},{{/@last}}
{{/allVars}}
)
}
}
{{/if}}
{{#allVars}}
{{#isEnum}}
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^@last}},{{/@last}}{{/enumVars}}{{/allowableValues}}
*/
/**
* {{{description}}}
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^@last}},{{/@last}}{{/enumVars}}{{/allowableValues}}
*/
enum class {{nameInCamelCase}}(val value: {{datatype}}{{#isNullable}}?{{/isNullable}}) {
{{#allowableValues}}{{#enumVars}}
{{&name}}({{#value}}{{{value}}}{{/value}}{{^value}}null{{/value}}){{^@last}},{{/@last}}{{#@last}};{{/@last}}

View File

@ -0,0 +1 @@
val {{{name}}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{#if vendorExtensions.x-is-date-format}}kotlin.String{{else}}{{{datatype}}}{{/if}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}

View File

@ -0,0 +1 @@
val {{{name}}}: {{#is this 'enum'}}{{datatypeWithEnum}}{{/is}}{{#isNot this 'enum'}}{{#if vendorExtensions.x-is-date-format}}kotlin.String{{else}}{{{datatype}}}{{/if}}{{/isNot}}

View File

@ -1,14 +1,10 @@
{{>licenseInfo}}
package {{modelPackage}}
import com.squareup.moshi.JsonClass
import com.squareup.moshi.ToJson
import com.squareup.moshi.FromJson
{{#imports}}import {{import}}
{{/imports}}
{{#jodaTime}}
import org.joda.time.DateTime
{{/jodaTime}}
{{#models}}
{{#model}}
@ -20,4 +16,4 @@ typealias {{classname}} = {{dataType}}
{{#isNot this 'enum'}}{{>data_class}}{{/isNot}}
{{/isNot}}
{{/model}}
{{/models}}
{{/models}}