From ed1ec9d5d45cee1fb9fb85d1288cd6cbc08e5741 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Wed, 29 May 2019 01:28:57 +0800 Subject: [PATCH 01/12] add kotlin-vertx --- .../languages/KotlinVertxServerCodegen.java | 213 ++++++++++++++++++ .../org.openapitools.codegen.CodegenConfig | 2 + .../kotlin-vertx-server/README.mustache | 0 .../kotlin-vertx-server/api.mustache | 15 ++ .../kotlin-vertx-server/apiError.mustache | 22 ++ .../kotlin-vertx-server/apiVerticle.mustache | 146 ++++++++++++ .../kotlin-vertx-server/enumClass.mustache | 17 ++ .../kotlin-vertx-server/model.mustache | 12 + .../kotlin-vertx-server/pojo.mustache | 74 ++++++ 9 files changed, 501 insertions(+) create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java new file mode 100644 index 000000000000..6b9bb3a744e4 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -0,0 +1,213 @@ +package org.openapitools.codegen.languages; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.servers.Server; +import org.openapitools.codegen.*; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; +import io.swagger.models.parameters.Parameter; + +import java.io.File; +import java.net.URL; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import org.openapitools.codegen.utils.URLPathUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KotlinVertxServerCodegen extends AbstractJavaCodegen { + + protected String rootPackage = "org.openapitools.server.api"; + protected String apiVersion = "1.0.0-SNAPSHOT"; + + public static final String ROOT_PACKAGE = "rootPackage"; + + public static final String PROJECT_NAME = "projectName"; + + static Logger LOGGER = LoggerFactory.getLogger(KotlinVertxServerCodegen.class); + + public CodegenType getTag() { + return CodegenType.SERVER; + } + + public String getName() { + return "kotlin-vertx"; + } + + public String getHelp() { + return "Generates a kotlin-vertx server."; + } + + public KotlinVertxServerCodegen() { + super(); + + importMapping.remove("JsonCreator"); + importMapping.remove("com.fasterxml.jackson.annotation.JsonProperty"); + importMapping.put("JsonInclude", "com.fasterxml.jackson.annotation.JsonInclude"); + importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); + importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); + + outputFolder = "generated-code" + File.separator + "kotlin-vertx"; + modelTemplateFiles.put("model.mustache", ".java"); + + apiTestTemplateFiles.clear(); + modelDocTemplateFiles.clear(); + apiDocTemplateFiles.clear(); + supportingFiles.clear(); + + apiTemplateFiles.clear(); + apiTemplateFiles.put("api.mustache", ".kt"); + apiTemplateFiles.put("apiVerticle.mustache", "Verticle.kt"); + apiTemplateFiles.put("apiError.mustache","Error.java"); +// apiTemplateFiles.put("apiException.mustache", "Exception.java"); + + this.setDateLibrary("java8"); + + embeddedTemplateDir = templateDir = "kotlin-vertx-server"; + apiPackage = rootPackage + ".verticle"; + modelPackage = rootPackage + ".model"; + artifactId = "openapi-java-vertx-server"; + artifactVersion = apiVersion; +// supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + + updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId()); + updateOption(CodegenConstants.ARTIFACT_VERSION, this.getArtifactVersion()); + updateOption(CodegenConstants.API_PACKAGE, apiPackage); + updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage); + updateOption(this.DATE_LIBRARY, this.getDateLibrary()); + additionalProperties.put(ROOT_PACKAGE, rootPackage); + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + if (!model.isEnum) { + model.imports.add("JsonInclude"); + model.imports.add("JsonProperty"); + if (model.hasEnums) { + model.imports.add("JsonValue"); + } + } + + } + + @Override + public Map postProcessOperationsWithModels(Map objs, List allModels) { + Map newObjs = super.postProcessOperationsWithModels(objs, allModels); + Map operations = (Map) newObjs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (CodegenOperation operation : ops) { + operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT); + + if ("Void".equalsIgnoreCase(operation.returnType)) { + operation.returnType = null; + } + + if (operation.getHasPathParams()) { + operation.path = camelizePath(operation.path); + } + + } + } + return newObjs; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + generateJSONSpecFile(objs); + return super.postProcessSupportingFileData(objs); + } + + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { + CodegenOperation codegenOperation = + super.fromOperation(path, httpMethod, operation, servers); + return codegenOperation; + } + + @Override + public CodegenModel fromModel(String name, Schema model) { + CodegenModel codegenModel = super.fromModel(name, model); + codegenModel.imports.remove("ApiModel"); + codegenModel.imports.remove("ApiModelProperty"); + return codegenModel; + } + + @Override + public void preprocessOpenAPI(OpenAPI openAPI) { + super.preprocessOpenAPI(openAPI); + + // add server port from the swagger file, 8080 by default + URL url = URLPathUtils.getServerURL(openAPI); + this.additionalProperties.put("serverPort", URLPathUtils.getPort(url, 8080)); + + Map paths = openAPI.getPaths(); + if (paths != null) { + for (Map.Entry entry : paths.entrySet()) { + manageOperationNames(entry.getValue(), entry.getKey()); + } + } + this.additionalProperties.remove("gson"); + } + + private void manageOperationNames(PathItem path, String pathname) { + String serviceIdTemp; + + Map operationMap = path.readOperationsMap(); + if (operationMap != null) { + for (Map.Entry entry : operationMap.entrySet()) { + serviceIdTemp = computeServiceId(pathname, entry); +// if(entry.getValue().getRequestBody()!=null){ +// entry.getValue().addExtension("body",entry.getValue().getRequestBody()); +// } + entry.getValue().addExtension("x-serviceid", serviceIdTemp); + entry.getValue().addExtension("x-serviceid-varname", + serviceIdTemp.toUpperCase(Locale.ROOT) + "_SERVICE_ID"); + } + } + } + + private String computeServiceId(String pathname, Map.Entry entry) { + String operationId = entry.getValue().getOperationId(); + return (operationId != null) ? operationId + : entry.getKey().name() + + pathname.replaceAll("-", "_").replaceAll("/", "_").replaceAll("[{}]", ""); + } + + protected String extractPortFromHost(String host) { + if (host != null) { + int portSeparatorIndex = host.indexOf(':'); + if (portSeparatorIndex >= 0 && portSeparatorIndex + 1 < host.length()) { + return host.substring(portSeparatorIndex + 1); + } + } + return "8080"; + } + + private String camelizePath(String path) { + String word = path; + Pattern pattern = Pattern.compile("\\{([^/]*)\\}"); + Matcher matcher = pattern.matcher(word); + while (matcher.find()) { + word = matcher.replaceFirst(":" + matcher.group(1)); + matcher = pattern.matcher(word); + } + pattern = Pattern.compile("(_)(.)"); + matcher = pattern.matcher(word); + while (matcher.find()) { + word = matcher.replaceFirst(matcher.group(2).toUpperCase(Locale.ROOT)); + matcher = pattern.matcher(word); + } + return word; + } +} diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 3f21ea57ec09..bd6cb955d130 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -107,3 +107,5 @@ org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen org.openapitools.codegen.languages.TypeScriptNodeClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen org.openapitools.codegen.languages.FsharpGiraffeServerCodegen + +org.openapitools.codegen.languages.KotlinVertxServerCodegen diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache new file mode 100644 index 000000000000..a1e9ace2f835 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -0,0 +1,15 @@ +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.util.List; +import java.util.Map; + +public interface {{classname}} { +{{#operations}} + {{#operation}} + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}):{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} + {{/operation}} +{{/operations}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache new file mode 100644 index 000000000000..21ae71e5f15d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache @@ -0,0 +1,22 @@ +package {{rootPackage}}; + +public class {{classname}}Error extends Exception { + private int statusCode; + private String statusMessage; + + public {{classname}}Error(int statusCode, String statusMessage) { + super(); + this.statusCode = statusCode; + this.statusMessage = statusMessage; + } + + public int getStatusCode() { + return statusCode; + } + + public String getStatusMessage() { + return statusMessage; + } + + public static final {{classname}}Error INTERNAL_SERVER_ERROR = new {{classname}}Error(500, "Internal Server Error"); +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache new file mode 100644 index 000000000000..6f2184b660a0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache @@ -0,0 +1,146 @@ +package {{package}} + +import io.vertx.core.AbstractVerticle +import io.vertx.core.eventbus.Message +import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import io.vertx.core.json.JsonObject +import io.vertx.core.logging.Logger +import io.vertx.core.logging.LoggerFactory +import io.vertx.ext.asyncsql.MySQLClient +import io.vertx.ext.asyncsql.AsyncSQLClient +import org.jooq.SQLDialect +import org.jooq.impl.DefaultConfiguration +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.swagger.parser.OpenAPIParser +import io.swagger.v3.oas.models.OpenAPI +import io.vertx.core.Vertx +import java.nio.charset.Charset + +{{#imports}}import {{import}}; +{{/imports}} + +class {{classname}}Verticle:AbstractVerticle() { + companion object { + fun register(vertx:Vertx,file:String): OpenAPI { + val vertxFileSystem = vertx.fileSystem() + val authBuffer = vertxFileSystem.readFileBlocking(file) + return OpenAPIParser().readContents(authBuffer.toString(Charset.forName("utf-8")), null, null).openAPI + } + } + {{#operations}}{{#operation}}{{#vendorExtensions}} + private val {{x-serviceid-varname}} = "{{x-serviceid}}" + {{/vendorExtensions}}{{/operation}}{{/operations}} + private val logger = LoggerFactory.getLogger(this::class.java) + private lateinit var service:{{classname}} + override fun start() { + super.start() + val configuration = DefaultConfiguration() + configuration.set(SQLDialect.MYSQL) //or SQLDialect.POSTGRES + val client = MySQLClient.createNonShared(vertx, config().getJsonObject("mysql")) + init(client) + {{#operations}}{{#operation}} + //Consumer for {{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}} + vertx.eventBus().consumer({{#vendorExtensions}}{{x-serviceid-varname}}{{/vendorExtensions}}).handler { message-> + try{ + val serviceId = "{{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}" + {{#hasParams}} + {{#allParams}} + {{#isListContainer}} + val {{paramName}}Param = message.body().getJsonArray("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} + if({{paramName}}Param == null) { + manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) + return@handler + } + val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param.encode(), + Json.mapper.getTypeFactory().constructCollectionType(List::class.java, {{{baseType}}}::class.java)) + {{/required}} + {{^required}} + val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} + else Json.mapper.readValue({{paramName}}Param.encode(), + Json.mapper.getTypeFactory().constructCollectionType(List::class.java, {{{baseType}}}::class.java)) + {{/required}} + {{/isListContainer}} + {{^isListContainer}} + {{#isPrimitiveType}} + {{#isString}} + val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} + if({{paramName}}Param == null) { + manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) + return@handler + } + val {{paramName}}:{{{dataType}}} = {{paramName}}Param + {{/required}} + {{^required}} + val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{#isEnum}}"{{/isEnum}}{{{defaultValue}}}{{#isEnum}}"{{/isEnum}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else {{paramName}}Param + {{/required}} + {{/isString}} + {{^isString}} + val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} + if({{paramName}}Param == null) { + manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) + return@handler + } + val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param, {{{dataType}}}::class.java) + {{/required}} + {{^required}} + val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else Json.mapper.readValue({{paramName}}Param, {{{dataType}}}::class.java) + {{/required}} + {{/isString}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + val {{paramName}}Param = message.body().getJsonObject("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + if ({{paramName}}Param == null) { + manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) + return@handler + } + val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/isPrimitiveType}} + {{/isListContainer}} + {{/allParams}} + {{/hasParams}} + GlobalScope.launch(vertx.dispatcher()){ + val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/allParams}}{{/hasParams}} + {{#returnType}} + {{#isListContainer}} + message.reply(JsonArray(Json.encode(result)).encodePrettily()) + {{/isListContainer}} + {{^isListContainer}} + message.reply(JsonObject(Json.encode(result)).encodePrettily()) + {{/isListContainer}} + {{/returnType}} + {{^returnType}} + message.reply(null) + {{/returnType}} + }.invokeOnCompletion { + if(it!=null) manageError(message, it, "{{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}") + } + }catch(e:Exception){ + logger.error("Unexpected error in {{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}",e) + } + } + {{/operation}}{{/operations}} + + } + + private fun manageError(message: Message, cause: Throwable, serviceName: String) { + var code = {{classname}}Error.INTERNAL_SERVER_ERROR.statusCode + var statusMessage = {{classname}}Error.INTERNAL_SERVER_ERROR.statusMessage + if (cause is {{classname}}Error) { + code = cause.statusCode + statusMessage = cause.statusMessage + } else { + logger.error(serviceName, cause) + } + message.fail(code, statusMessage) + } + + fun init(client:AsyncSQLClient){ + + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache new file mode 100644 index 000000000000..0867107d9930 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enumClass.mustache @@ -0,0 +1,17 @@ + + public enum {{{datatypeWithEnum}}} { + {{#allowableValues}}{{#enumVars}}{{{name}}}({{{value}}}){{^-last}}, + {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} + + private String value; + + {{{datatypeWithEnum}}}(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache new file mode 100644 index 000000000000..787fe8e17c0c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache @@ -0,0 +1,12 @@ +package {{package}}; + +import java.util.Objects; +{{#imports}}import {{import}}; +{{/imports}} +{{#serializableModel}}import java.io.Serializable; +{{/serializableModel}}{{#models}}{{#model}}{{#description}} + /** + * {{description}} + **/ +{{/description}}{{^description}} +{{/description}}{{#isEnum}}{{>enumOuterClass}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}}{{/model}}{{/models}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache new file mode 100644 index 000000000000..95dcd9813e7f --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache @@ -0,0 +1,74 @@ +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} { + {{#vars}}{{#isEnum}}{{^isContainer}} + +{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} + +{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/vars}} + + public {{classname}} () { + + } + + public {{classname}} ({{#vars}}{{{datatypeWithEnum}}} {{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}) { + {{#vars}} + this.{{name}} = {{name}}; + {{/vars}} + } + + {{#vars}} + {{#vendorExtensions.extraAnnotation}}{{vendorExtensions.extraAnnotation}}{{/vendorExtensions.extraAnnotation}} + @JsonProperty("{{baseName}}") + public {{{datatypeWithEnum}}} {{getter}}() { + return {{name}}; + } + public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + this.{{name}} = {{name}}; + } + + {{/vars}} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + {{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}} + return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} && + {{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} From fcdc0517a4169971faa12f3a5fb175d48ec6b66b Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Wed, 29 May 2019 01:30:20 +0800 Subject: [PATCH 02/12] add kotlin-vertx --- bin/kotlin-vertx-server-petstore.sh | 31 ++++++++++++++++++++ bin/windows/kotlin-vertx-server-petstore.bat | 10 +++++++ 2 files changed, 41 insertions(+) create mode 100755 bin/kotlin-vertx-server-petstore.sh create mode 100644 bin/windows/kotlin-vertx-server-petstore.bat diff --git a/bin/kotlin-vertx-server-petstore.sh b/bin/kotlin-vertx-server-petstore.sh new file mode 100755 index 000000000000..73d0d087f3bd --- /dev/null +++ b/bin/kotlin-vertx-server-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=$(ls -ld "$SCRIPT") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=$(dirname "$SCRIPT")/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=$(dirname "$SCRIPT")/.. + APP_DIR=$(cd "${APP_DIR}"; pwd) +fi + +executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g kotlin-vertx -o samples/server/petstore/kotlin/vertx" + +java ${JAVA_OPTS} -jar ${executable} ${ags} diff --git a/bin/windows/kotlin-vertx-server-petstore.bat b/bin/windows/kotlin-vertx-server-petstore.bat new file mode 100644 index 000000000000..6fd12f43d82c --- /dev/null +++ b/bin/windows/kotlin-vertx-server-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties +set ags=generate --artifact-id "kotlin-vertx-petstore-server" -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g kotlin-vertx -o samples\server\petstore\kotlin\vertx + +java %JAVA_OPTS% -jar %executable% %ags% From 7225badfa907c88701844453952f31becca7ffb9 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Wed, 29 May 2019 22:28:24 +0800 Subject: [PATCH 03/12] update kotlin server --- .../languages/KotlinVertxServerCodegen.java | 5 +- .../kotlin-vertx-server/README.mustache | 3 + .../kotlin-vertx-server/api.mustache | 15 +- .../kotlin-vertx-server/apiError.mustache | 2 +- .../kotlin-vertx-server/apiVerticle.mustache | 43 ++--- .../kotlin-vertx-server/main.mustache | 21 +++ .../kotlin-vertx-server/pom.mustache | 173 ++++++++++++++++++ 7 files changed, 227 insertions(+), 35 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index 6b9bb3a744e4..bf243b720218 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -67,8 +67,7 @@ public KotlinVertxServerCodegen() { apiTemplateFiles.put("api.mustache", ".kt"); apiTemplateFiles.put("apiVerticle.mustache", "Verticle.kt"); apiTemplateFiles.put("apiError.mustache","Error.java"); -// apiTemplateFiles.put("apiException.mustache", "Exception.java"); - + apiTemplateFiles.put("main.mustache","Main.kt"); this.setDateLibrary("java8"); embeddedTemplateDir = templateDir = "kotlin-vertx-server"; @@ -84,6 +83,8 @@ public KotlinVertxServerCodegen() { updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage); updateOption(this.DATE_LIBRARY, this.getDateLibrary()); additionalProperties.put(ROOT_PACKAGE, rootPackage); + + supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); } @Override diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache index e69de29bb2d1..39a1a6364f83 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache @@ -0,0 +1,3 @@ +{{^hideGenerationTimestamp}} + Project generated on : {{generatedDate}} +{{/hideGenerationTimestamp}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache index a1e9ace2f835..7a1e4ed2d9c4 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -1,15 +1,18 @@ package {{package}}; -{{#imports}}import {{import}}; +{{#imports}}import {{import}} {{/imports}} +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject +import com.github.wooyme.openapi.Response +import java.util.List +import java.util.Map -import java.util.List; -import java.util.Map; - -public interface {{classname}} { +interface {{classname}} { + fun init(vertx:Vertx,config:JsonObject) {{#operations}} {{#operation}} - suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}):{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}},session:JsonObject?):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{/operation}} {{/operations}} } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache index 21ae71e5f15d..27e3f24a4f32 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache @@ -1,4 +1,4 @@ -package {{rootPackage}}; +package {{package}}; public class {{classname}}Error extends Exception { private int statusCode; diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache index 6f2184b660a0..9a8b579aecb9 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache @@ -7,40 +7,37 @@ import io.vertx.core.json.JsonArray import io.vertx.core.json.JsonObject import io.vertx.core.logging.Logger import io.vertx.core.logging.LoggerFactory -import io.vertx.ext.asyncsql.MySQLClient -import io.vertx.ext.asyncsql.AsyncSQLClient -import org.jooq.SQLDialect -import org.jooq.impl.DefaultConfiguration import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import io.vertx.kotlin.coroutines.dispatcher +import com.github.wooyme.openapi.SwaggerRouter import io.swagger.parser.OpenAPIParser import io.swagger.v3.oas.models.OpenAPI import io.vertx.core.Vertx +import io.vertx.ext.web.Router import java.nio.charset.Charset +import com.github.wooyme.openapi.Response {{#imports}}import {{import}}; {{/imports}} -class {{classname}}Verticle:AbstractVerticle() { +class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle() { companion object { - fun register(vertx:Vertx,file:String): OpenAPI { + fun register(vertx:Vertx,file:String,router:Router) { val vertxFileSystem = vertx.fileSystem() val authBuffer = vertxFileSystem.readFileBlocking(file) - return OpenAPIParser().readContents(authBuffer.toString(Charset.forName("utf-8")), null, null).openAPI + val result = OpenAPIParser().readContents(authBuffer.toString(Charset.forName("utf-8")), null, null).openAPI + SwaggerRouter.swaggerRouter(router, result, vertx.eventBus()) } } {{#operations}}{{#operation}}{{#vendorExtensions}} private val {{x-serviceid-varname}} = "{{x-serviceid}}" {{/vendorExtensions}}{{/operation}}{{/operations}} private val logger = LoggerFactory.getLogger(this::class.java) - private lateinit var service:{{classname}} + override fun start() { super.start() - val configuration = DefaultConfiguration() - configuration.set(SQLDialect.MYSQL) //or SQLDialect.POSTGRES - val client = MySQLClient.createNonShared(vertx, config().getJsonObject("mysql")) - init(client) + service.init(vertx,config()) {{#operations}}{{#operation}} //Consumer for {{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}} vertx.eventBus().consumer({{#vendorExtensions}}{{x-serviceid-varname}}{{/vendorExtensions}}).handler { message-> @@ -104,19 +101,17 @@ class {{classname}}Verticle:AbstractVerticle() { {{/isListContainer}} {{/allParams}} {{/hasParams}} + val session = message.body().getJsonObject("session"); GlobalScope.launch(vertx.dispatcher()){ - val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{^hasMore}}){{/hasMore}}{{/allParams}}{{/hasParams}} + val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{/hasParams}},session) + val json = JsonObject() + if(result.session!=null){ + json.put("session",result.session) + } {{#returnType}} - {{#isListContainer}} - message.reply(JsonArray(Json.encode(result)).encodePrettily()) - {{/isListContainer}} - {{^isListContainer}} - message.reply(JsonObject(Json.encode(result)).encodePrettily()) - {{/isListContainer}} - {{/returnType}} - {{^returnType}} - message.reply(null) + json.put("body",Json.encode(result.body)) {{/returnType}} + message.reply(json) }.invokeOnCompletion { if(it!=null) manageError(message, it, "{{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}") } @@ -139,8 +134,4 @@ class {{classname}}Verticle:AbstractVerticle() { } message.fail(code, statusMessage) } - - fun init(client:AsyncSQLClient){ - - } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache new file mode 100644 index 000000000000..eb60d0342a36 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache @@ -0,0 +1,21 @@ +package {{package}} + +import io.vertx.core.Vertx +import io.vertx.ext.web.Router +import io.vertx.ext.web.handler.BodyHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.SessionStore + +fun main(args:Array){ + val vertx = Vertx.vertx() + val httpServer = vertx.createHttpServer() + val router = Router.router(vertx) + router.route().handler(BodyHandler.create()) + router.route().handler(SessionHandler.create(SessionStore.create(vertx))) + {{classname}}Verticle.register(vertx,if(args.size>1) args[1] else "openapi.json",router) + //vertx.deployVerticle(DefaultApiVerticle(DefaultApiImpl(...))) + httpServer.requestHandler(router).listen({{serverPort}}){ + if(it.failed()) it.cause().printStackTrace() + else println("Listen at {{serverPort}} !") + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache new file mode 100644 index 000000000000..20ae0b61b3bd --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache @@ -0,0 +1,173 @@ + + 4.0.0 + + {{groupId}} + {{artifactId}} + {{artifactVersion}} + jar + + {{appName}} + + + UTF-8 + 1.8 + 1.3.10 + true + 4.12 + 3.4.1 + 3.3 + 1.0.1 + 2.3 + 2.7.4 + 3.6.0 + + + + + junit + junit + ${junit.version} + test + + + + io.vertx + vertx-unit + ${vertx.version} + test + + + + com.github.wooyme + vertx-openapi-router + ${vertx-openapi-router.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-datatype-jsr310.version} + + + javax.annotation + javax.annotation-api + 1.2 + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + RELEASE + + + + io.vertx + vertx-core + ${vertx.version} + + + io.vertx + vertx-web + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin + ${vertx.version} + + + + io.vertx + vertx-lang-kotlin-coroutines + ${vertx.version} + + + + io.swagger.parser.v3 + swagger-parser + 2.0.5 + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + ${project.basedir}/src/main/jooq + + 1.8 + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + ${project.basedir}/src/main/jooq + + 1.8 + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + io.vertx.core.Starter + {{rootPackage}}.MainApiVerticle + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar + + + + + + + \ No newline at end of file From aaf63bf9de854e5405781286d4b817bd92486108 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Thu, 30 May 2019 14:27:27 +0800 Subject: [PATCH 04/12] update --- .../languages/KotlinVertxServerCodegen.java | 21 ++++- .../org.openapitools.codegen.CodegenConfig | 3 +- .../kotlin-vertx-server/README.mustache | 79 ++++++++++++++++++- .../kotlin-vertx-server/api_doc.mustache | 42 ++++++++++ 4 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index bf243b720218..69d8b7d48f2b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -1,3 +1,19 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * + * 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 + * + * http://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. + */ + package org.openapitools.codegen.languages; import io.swagger.v3.oas.models.OpenAPI; @@ -60,7 +76,7 @@ public KotlinVertxServerCodegen() { apiTestTemplateFiles.clear(); modelDocTemplateFiles.clear(); - apiDocTemplateFiles.clear(); +// apiDocTemplateFiles.clear(); supportingFiles.clear(); apiTemplateFiles.clear(); @@ -75,7 +91,6 @@ public KotlinVertxServerCodegen() { modelPackage = rootPackage + ".model"; artifactId = "openapi-java-vertx-server"; artifactVersion = apiVersion; -// supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId()); updateOption(CodegenConstants.ARTIFACT_VERSION, this.getArtifactVersion()); @@ -85,6 +100,8 @@ public KotlinVertxServerCodegen() { additionalProperties.put(ROOT_PACKAGE, rootPackage); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); + supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + } @Override diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index bd6cb955d130..9b818dbfd752 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -36,6 +36,7 @@ org.openapitools.codegen.languages.GroovyClientCodegen org.openapitools.codegen.languages.KotlinClientCodegen org.openapitools.codegen.languages.KotlinServerCodegen org.openapitools.codegen.languages.KotlinSpringServerCodegen +org.openapitools.codegen.languages.KotlinVertxServerCodegen org.openapitools.codegen.languages.HaskellHttpClientCodegen org.openapitools.codegen.languages.HaskellServantCodegen org.openapitools.codegen.languages.JavaClientCodegen @@ -107,5 +108,3 @@ org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen org.openapitools.codegen.languages.TypeScriptNodeClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen org.openapitools.codegen.languages.FsharpGiraffeServerCodegen - -org.openapitools.codegen.languages.KotlinVertxServerCodegen diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache index 39a1a6364f83..f4db05742d00 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/README.mustache @@ -1,3 +1,76 @@ -{{^hideGenerationTimestamp}} - Project generated on : {{generatedDate}} -{{/hideGenerationTimestamp}} +# {{packageName}} - Kotlin Server library for {{appName}} + +## Requires + +* Kotlin 1.3.10 +* Maven 3.3 + +## Build + +``` +mvn clean package +``` + +This runs all tests and packages the library. + +## Features/Implementation Notes + +* Supports JSON inputs/outputs and Form inputs. +* Supports collection formats for query parameters: csv, tsv, ssv, pipes. +* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. + +{{#generateApiDocs}} + + ## 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}} + + ## Documentation for Models + + {{#modelPackage}} + {{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) + {{/model}}{{/models}} + {{/modelPackage}} + {{^modelPackage}} + No model defined in this package + {{/modelPackage}} +{{/generateModelDocs}} + +{{! 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}} + + ### {{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}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache new file mode 100644 index 000000000000..5a41503df5b9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_doc.mustache @@ -0,0 +1,42 @@ +# {{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}} + +# **{{operationId}}** +> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{summary}}{{#notes}} + +{{notes}}{{/notes}} + +### 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}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{/operation}} +{{/operations}} From 56ffbc2c380c2a389dbdea2c098ac6d5a54407c9 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Thu, 30 May 2019 14:34:25 +0800 Subject: [PATCH 05/12] move Fsharp... in Config --- .../META-INF/services/org.openapitools.codegen.CodegenConfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig index 9b818dbfd752..d2d7c3b2faf2 100644 --- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig +++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig @@ -27,6 +27,7 @@ org.openapitools.codegen.languages.ErlangClientCodegen org.openapitools.codegen.languages.ErlangProperCodegen org.openapitools.codegen.languages.ErlangServerCodegen org.openapitools.codegen.languages.FlashClientCodegen +org.openapitools.codegen.languages.FsharpGiraffeServerCodegen org.openapitools.codegen.languages.GoClientCodegen org.openapitools.codegen.languages.GoServerCodegen org.openapitools.codegen.languages.GoGinServerCodegen @@ -107,4 +108,4 @@ org.openapitools.codegen.languages.TypeScriptInversifyClientCodegen org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen org.openapitools.codegen.languages.TypeScriptNodeClientCodegen org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen -org.openapitools.codegen.languages.FsharpGiraffeServerCodegen + From 42aafa4b6be23e7651a985a7623be1ce86481271 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Fri, 31 May 2019 14:20:43 +0800 Subject: [PATCH 06/12] replace java model to kotlin model. delete useless code --- .../languages/KotlinVertxServerCodegen.java | 169 +----------------- .../kotlin-vertx-server/api.mustache | 4 +- .../kotlin-vertx-server/apiError.mustache | 21 +-- .../kotlin-vertx-server/apiVerticle.mustache | 82 +++++---- .../kotlin-vertx-server/class_doc.mustache | 15 ++ .../kotlin-vertx-server/data_class.mustache | 33 ++++ .../data_class_opt_var.mustache | 4 + .../data_class_req_var.mustache | 4 + .../kotlin-vertx-server/enum_class.mustache | 9 + .../kotlin-vertx-server/enum_doc.mustache | 7 + .../kotlin-vertx-server/licenseInfo.mustache | 11 ++ .../kotlin-vertx-server/main.mustache | 4 +- .../kotlin-vertx-server/model.mustache | 19 +- .../kotlin-vertx-server/pojo.mustache | 74 -------- .../kotlin-vertx-server/pom.mustache | 13 +- 15 files changed, 160 insertions(+), 309 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache delete mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index 69d8b7d48f2b..62e17f229de2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -16,30 +16,15 @@ package org.openapitools.codegen.languages; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.servers.Server; -import org.openapitools.codegen.*; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.parameters.Parameter; - -import java.io.File; -import java.net.URL; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; - -import org.openapitools.codegen.utils.URLPathUtils; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenType; +import org.openapitools.codegen.SupportingFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class KotlinVertxServerCodegen extends AbstractJavaCodegen { +import java.io.File; + +public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { protected String rootPackage = "org.openapitools.server.api"; protected String apiVersion = "1.0.0-SNAPSHOT"; @@ -65,167 +50,31 @@ public String getHelp() { public KotlinVertxServerCodegen() { super(); - importMapping.remove("JsonCreator"); - importMapping.remove("com.fasterxml.jackson.annotation.JsonProperty"); - importMapping.put("JsonInclude", "com.fasterxml.jackson.annotation.JsonInclude"); - importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); - importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue"); - outputFolder = "generated-code" + File.separator + "kotlin-vertx"; - modelTemplateFiles.put("model.mustache", ".java"); + modelTemplateFiles.put("model.mustache", ".kt"); apiTestTemplateFiles.clear(); modelDocTemplateFiles.clear(); -// apiDocTemplateFiles.clear(); supportingFiles.clear(); apiTemplateFiles.clear(); apiTemplateFiles.put("api.mustache", ".kt"); apiTemplateFiles.put("apiVerticle.mustache", "Verticle.kt"); - apiTemplateFiles.put("apiError.mustache","Error.java"); + apiTemplateFiles.put("apiError.mustache","Error.kt"); apiTemplateFiles.put("main.mustache","Main.kt"); - this.setDateLibrary("java8"); embeddedTemplateDir = templateDir = "kotlin-vertx-server"; apiPackage = rootPackage + ".verticle"; modelPackage = rootPackage + ".model"; - artifactId = "openapi-java-vertx-server"; + artifactId = "openapi-kotlin-vertx-server"; artifactVersion = apiVersion; - updateOption(CodegenConstants.ARTIFACT_ID, this.getArtifactId()); - updateOption(CodegenConstants.ARTIFACT_VERSION, this.getArtifactVersion()); updateOption(CodegenConstants.API_PACKAGE, apiPackage); updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage); - updateOption(this.DATE_LIBRARY, this.getDateLibrary()); additionalProperties.put(ROOT_PACKAGE, rootPackage); supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - super.postProcessModelProperty(model, property); - if (!model.isEnum) { - model.imports.add("JsonInclude"); - model.imports.add("JsonProperty"); - if (model.hasEnums) { - model.imports.add("JsonValue"); - } - } - - } - - @Override - public Map postProcessOperationsWithModels(Map objs, List allModels) { - Map newObjs = super.postProcessOperationsWithModels(objs, allModels); - Map operations = (Map) newObjs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (CodegenOperation operation : ops) { - operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT); - - if ("Void".equalsIgnoreCase(operation.returnType)) { - operation.returnType = null; - } - - if (operation.getHasPathParams()) { - operation.path = camelizePath(operation.path); - } - - } - } - return newObjs; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - generateJSONSpecFile(objs); - return super.postProcessSupportingFileData(objs); - } - - - @Override - public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { - CodegenOperation codegenOperation = - super.fromOperation(path, httpMethod, operation, servers); - return codegenOperation; - } - - @Override - public CodegenModel fromModel(String name, Schema model) { - CodegenModel codegenModel = super.fromModel(name, model); - codegenModel.imports.remove("ApiModel"); - codegenModel.imports.remove("ApiModelProperty"); - return codegenModel; - } - - @Override - public void preprocessOpenAPI(OpenAPI openAPI) { - super.preprocessOpenAPI(openAPI); - - // add server port from the swagger file, 8080 by default - URL url = URLPathUtils.getServerURL(openAPI); - this.additionalProperties.put("serverPort", URLPathUtils.getPort(url, 8080)); - - Map paths = openAPI.getPaths(); - if (paths != null) { - for (Map.Entry entry : paths.entrySet()) { - manageOperationNames(entry.getValue(), entry.getKey()); - } - } - this.additionalProperties.remove("gson"); - } - - private void manageOperationNames(PathItem path, String pathname) { - String serviceIdTemp; - - Map operationMap = path.readOperationsMap(); - if (operationMap != null) { - for (Map.Entry entry : operationMap.entrySet()) { - serviceIdTemp = computeServiceId(pathname, entry); -// if(entry.getValue().getRequestBody()!=null){ -// entry.getValue().addExtension("body",entry.getValue().getRequestBody()); -// } - entry.getValue().addExtension("x-serviceid", serviceIdTemp); - entry.getValue().addExtension("x-serviceid-varname", - serviceIdTemp.toUpperCase(Locale.ROOT) + "_SERVICE_ID"); - } - } - } - - private String computeServiceId(String pathname, Map.Entry entry) { - String operationId = entry.getValue().getOperationId(); - return (operationId != null) ? operationId - : entry.getKey().name() - + pathname.replaceAll("-", "_").replaceAll("/", "_").replaceAll("[{}]", ""); - } - - protected String extractPortFromHost(String host) { - if (host != null) { - int portSeparatorIndex = host.indexOf(':'); - if (portSeparatorIndex >= 0 && portSeparatorIndex + 1 < host.length()) { - return host.substring(portSeparatorIndex + 1); - } - } - return "8080"; - } - - private String camelizePath(String path) { - String word = path; - Pattern pattern = Pattern.compile("\\{([^/]*)\\}"); - Matcher matcher = pattern.matcher(word); - while (matcher.find()) { - word = matcher.replaceFirst(":" + matcher.group(1)); - matcher = pattern.matcher(word); - } - pattern = Pattern.compile("(_)(.)"); - matcher = pattern.matcher(word); - while (matcher.find()) { - word = matcher.replaceFirst(matcher.group(2).toUpperCase(Locale.ROOT)); - matcher = pattern.matcher(word); - } - return word; - } } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache index 7a1e4ed2d9c4..7f0755a34c99 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -12,7 +12,9 @@ interface {{classname}} { fun init(vertx:Vertx,config:JsonObject) {{#operations}} {{#operation}} - suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}},session:JsonObject?):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + /* {{operationId}} + * {{summary}} */ + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{^isRequired}}?{{/isRequired}},{{/allParams}}session:JsonObject?):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{/operation}} {{/operations}} } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache index 27e3f24a4f32..46f44e470e5a 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache @@ -1,22 +1,7 @@ package {{package}}; -public class {{classname}}Error extends Exception { - private int statusCode; - private String statusMessage; - - public {{classname}}Error(int statusCode, String statusMessage) { - super(); - this.statusCode = statusCode; - this.statusMessage = statusMessage; - } - - public int getStatusCode() { - return statusCode; - } - - public String getStatusMessage() { - return statusMessage; +class {{classname}}Error(val statusCode:Int,val statusMessage:String):Exception() { + companion object { + val INTERNAL_SERVER_ERROR = {{classname}}Error(500, "Internal Server Error") } - - public static final {{classname}}Error INTERNAL_SERVER_ERROR = new {{classname}}Error(500, "Internal Server Error"); } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache index 9a8b579aecb9..98eb78d9f7f5 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache @@ -5,6 +5,7 @@ import io.vertx.core.eventbus.Message import io.vertx.core.json.Json import io.vertx.core.json.JsonArray import io.vertx.core.json.JsonObject +import com.google.gson.Gson import io.vertx.core.logging.Logger import io.vertx.core.logging.LoggerFactory import kotlinx.coroutines.GlobalScope @@ -18,7 +19,7 @@ import io.vertx.ext.web.Router import java.nio.charset.Charset import com.github.wooyme.openapi.Response -{{#imports}}import {{import}}; +{{#imports}}import {{import}} {{/imports}} class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle() { @@ -30,19 +31,16 @@ class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle( SwaggerRouter.swaggerRouter(router, result, vertx.eventBus()) } } - {{#operations}}{{#operation}}{{#vendorExtensions}} - private val {{x-serviceid-varname}} = "{{x-serviceid}}" - {{/vendorExtensions}}{{/operation}}{{/operations}} private val logger = LoggerFactory.getLogger(this::class.java) override fun start() { super.start() service.init(vertx,config()) {{#operations}}{{#operation}} - //Consumer for {{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}} - vertx.eventBus().consumer({{#vendorExtensions}}{{x-serviceid-varname}}{{/vendorExtensions}}).handler { message-> + //Consumer for {{#vendorExtensions}}{{operationId}}{{/vendorExtensions}} + vertx.eventBus().consumer({{#vendorExtensions}}"{{operationId}}"{{/vendorExtensions}}).handler { message-> try{ - val serviceId = "{{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}" + val serviceId = "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}" {{#hasParams}} {{#allParams}} {{#isListContainer}} @@ -52,58 +50,68 @@ class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle( manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) return@handler } - val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param.encode(), - Json.mapper.getTypeFactory().constructCollectionType(List::class.java, {{{baseType}}}::class.java)) + val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() + , object : TypeToken>(){}.type) {{/required}} {{^required}} - val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} - else Json.mapper.readValue({{paramName}}Param.encode(), - Json.mapper.getTypeFactory().constructCollectionType(List::class.java, {{{baseType}}}::class.java)) + val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} + else Gson().fromJson({{paramName}}Param.encode(), + , object : TypeToken>(){}.type) {{/required}} {{/isListContainer}} {{^isListContainer}} {{#isPrimitiveType}} - {{#isString}} - val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") - {{#required}} - if({{paramName}}Param == null) { - manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) - return@handler - } - val {{paramName}}:{{{dataType}}} = {{paramName}}Param - {{/required}} - {{^required}} - val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{#isEnum}}"{{/isEnum}}{{{defaultValue}}}{{#isEnum}}"{{/isEnum}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else {{paramName}}Param - {{/required}} - {{/isString}} - {{^isString}} val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") - {{#required}} + {{#required}} if({{paramName}}Param == null) { manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) return@handler } - val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param, {{{dataType}}}::class.java) - {{/required}} - {{^required}} - val {{paramName}}:{{{dataType}}} = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else Json.mapper.readValue({{paramName}}Param, {{{dataType}}}::class.java) - {{/required}} + {{/required}} + {{#isString}} + val {{paramName}} = {{paramName}}Param {{/isString}} + {{#isNumber}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toBigDecimal() + {{/isNumber}} + {{#isLong}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toLong() + {{/isLong}} + {{#isInteger}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toInt() + {{/isInteger}} + {{#isFloat}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toFloat() + {{/isFloat}} + {{#isDouble}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toDouble() + {{/isDouble}} + {{#isBoolean}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toBoolean() + {{/isBoolean}} + {{#isFreeFormObject}} + val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.let{ try { JsonObject({{paramName}}Param) }catch( e:Exception ){ {{paramName}}Param } } + {{/isFreeFormObject}} {{/isPrimitiveType}} {{^isPrimitiveType}} val {{paramName}}Param = message.body().getJsonObject("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} if ({{paramName}}Param == null) { manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) return@handler } - val {{paramName}}:{{{dataType}}} = Json.mapper.readValue({{paramName}}Param.encode(), {{{dataType}}}::class.java) + val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} + {{^required}} + val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} {{/isPrimitiveType}} {{/isListContainer}} {{/allParams}} {{/hasParams}} - val session = message.body().getJsonObject("session"); + val session = message.body().getJsonObject("session") GlobalScope.launch(vertx.dispatcher()){ - val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{/hasParams}},session) + val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}},{{/allParams}}{{/hasParams}}session) val json = JsonObject() if(result.session!=null){ json.put("session",result.session) @@ -113,10 +121,10 @@ class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle( {{/returnType}} message.reply(json) }.invokeOnCompletion { - if(it!=null) manageError(message, it, "{{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}") + if(it!=null) manageError(message, it, "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}") } }catch(e:Exception){ - logger.error("Unexpected error in {{#vendorExtensions}}{{x-serviceid}}{{/vendorExtensions}}",e) + logger.error("Unexpected error in {{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}",e) } } {{/operation}}{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache new file mode 100644 index 000000000000..b363fc5a61f2 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/class_doc.mustache @@ -0,0 +1,15 @@ +# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isEnum}}[**inline**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} +{{/vars}} +{{#vars}}{{#isEnum}} + +{{!NOTE: see java's resources "pojo_doc.mustache" once enums are fully implemented}} +## Enum: {{baseName}} +Name | Value +---- | -----{{#allowableValues}} +{{name}} | {{#values}}{{.}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}} +{{/isEnum}}{{/vars}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache new file mode 100644 index 000000000000..feb6a0b317e6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache @@ -0,0 +1,33 @@ +{{#parcelizeModels}} +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +{{/parcelizeModels}} +/** + * {{{description}}} +{{#vars}} + * @param {{name}} {{{description}}} +{{/vars}} + */ +{{#parcelizeModels}} +@Parcelize +{{/parcelizeModels}} +data class {{classname}} ( +{{#requiredVars}} +{{>data_class_req_var}}{{^-last}}, +{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}}, +{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}}, +{{/-last}}{{/optionalVars}} +){{#parcelizeModels}} : Parcelable{{/parcelizeModels}} { +{{#hasEnums}}{{#vars}}{{#isEnum}} + /** + * {{{description}}} + * Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} + */ + enum class {{nameInCamelCase}}(val value: {{dataType}}){ + {{#allowableValues}}{{#enumVars}} + {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} + {{/enumVars}}{{/allowableValues}} + } +{{/isEnum}}{{/vars}}{{/hasEnums}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache new file mode 100644 index 000000000000..8bcc20d0fcac --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache @@ -0,0 +1,4 @@ +{{#description}} + /* {{{description}}} */ +{{/description}} + val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache new file mode 100644 index 000000000000..f8ffa6cde827 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache @@ -0,0 +1,4 @@ +{{#description}} + /* {{{description}}} */ +{{/description}} + val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache new file mode 100644 index 000000000000..791398b97894 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_class.mustache @@ -0,0 +1,9 @@ +/** +* {{{description}}} +* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} +*/ +enum class {{classname}}(val value: {{dataType}}){ +{{#allowableValues}}{{#enumVars}} + {{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} +{{/enumVars}}{{/allowableValues}} +} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache new file mode 100644 index 000000000000..fcb3d7e61aa6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/enum_doc.mustache @@ -0,0 +1,7 @@ +# {{classname}} + +## Enum + +{{#allowableValues}}{{#enumVars}} + * `{{name}}` (value: `{{{value}}}`) +{{/enumVars}}{{/allowableValues}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache new file mode 100644 index 000000000000..3a547de74bb7 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/licenseInfo.mustache @@ -0,0 +1,11 @@ +/** +* {{{appName}}} +* {{{appDescription}}} +* +* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} +* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache index eb60d0342a36..dfb4deb3d307 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache @@ -14,8 +14,8 @@ fun main(args:Array){ router.route().handler(SessionHandler.create(SessionStore.create(vertx))) {{classname}}Verticle.register(vertx,if(args.size>1) args[1] else "openapi.json",router) //vertx.deployVerticle(DefaultApiVerticle(DefaultApiImpl(...))) - httpServer.requestHandler(router).listen({{serverPort}}){ + httpServer.requestHandler(router).listen(80){ if(it.failed()) it.cause().printStackTrace() - else println("Listen at {{serverPort}} !") + else println("Listen at 80 !") } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache index 787fe8e17c0c..74b63c00c6f5 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/model.mustache @@ -1,12 +1,11 @@ -package {{package}}; +{{>licenseInfo}} +package {{modelPackage}} -import java.util.Objects; -{{#imports}}import {{import}}; +{{#imports}}import {{import}} {{/imports}} -{{#serializableModel}}import java.io.Serializable; -{{/serializableModel}}{{#models}}{{#model}}{{#description}} - /** - * {{description}} - **/ -{{/description}}{{^description}} -{{/description}}{{#isEnum}}{{>enumOuterClass}}{{/isEnum}}{{^isEnum}}{{>pojo}}{{/isEnum}}{{/model}}{{/models}} \ No newline at end of file + +{{#models}} + {{#model}} + {{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}}{{>data_class}}{{/isEnum}} + {{/model}} +{{/models}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache deleted file mode 100644 index 95dcd9813e7f..000000000000 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pojo.mustache +++ /dev/null @@ -1,74 +0,0 @@ -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown = true) -public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#serializableModel}}implements Serializable{{/serializableModel}} { - {{#vars}}{{#isEnum}}{{^isContainer}} - -{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} - -{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}} - private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};{{/vars}} - - public {{classname}} () { - - } - - public {{classname}} ({{#vars}}{{{datatypeWithEnum}}} {{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}) { - {{#vars}} - this.{{name}} = {{name}}; - {{/vars}} - } - - {{#vars}} - {{#vendorExtensions.extraAnnotation}}{{vendorExtensions.extraAnnotation}}{{/vendorExtensions.extraAnnotation}} - @JsonProperty("{{baseName}}") - public {{{datatypeWithEnum}}} {{getter}}() { - return {{name}}; - } - public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; - } - - {{/vars}} - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - {{classname}} {{classVarName}} = ({{classname}}) o;{{#hasVars}} - return {{#vars}}Objects.equals({{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{^hasMore}};{{/hasMore}}{{/vars}}{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } - - @Override - public int hashCode() { - return Objects.hash({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class {{classname}} {\n"); - {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} - {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); - {{/vars}}sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } -} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache index 20ae0b61b3bd..a0d13ba26c68 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache @@ -43,11 +43,13 @@ vertx-openapi-router ${vertx-openapi-router.version} + - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-datatype-jsr310.version} + com.google.code.gson + gson + 2.8.5 + javax.annotation javax.annotation-api @@ -111,7 +113,6 @@ ${project.basedir}/src/main/kotlin ${project.basedir}/src/main/java - ${project.basedir}/src/main/jooq 1.8 @@ -125,7 +126,6 @@ ${project.basedir}/src/test/kotlin ${project.basedir}/src/test/java - ${project.basedir}/src/main/jooq 1.8 @@ -157,8 +157,7 @@ - io.vertx.core.Starter - {{rootPackage}}.MainApiVerticle + {{apiPackage}}.DefaultApiMainKt From 8a4de49512849b3620d3aaf0dd2905eaea008e00 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Sat, 1 Jun 2019 23:05:18 +0800 Subject: [PATCH 07/12] add kotlin-vertx readme.md --- docs/generators/kotlin-vertx.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 docs/generators/kotlin-vertx.md diff --git a/docs/generators/kotlin-vertx.md b/docs/generators/kotlin-vertx.md new file mode 100644 index 000000000000..6759792afbf8 --- /dev/null +++ b/docs/generators/kotlin-vertx.md @@ -0,0 +1,18 @@ + +--- +id: generator-opts-server-kotlin-vertx +title: Config Options for kotlin-vertx +sidebar_label: kotlin-vertx +--- + +| Option | Description | Values | Default | +| ------ | ----------- | ------ | ------- | +|sourceFolder|source folder for generated code| |src/main/kotlin| +|modelPackage|package for generated models| |org.openapitools.server.api.model| +|apiPackage|package for generated api classes| |org.openapitools.server.api.verticle| +|apiSuffix|suffix for api classes| |Api| +|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools| +|artifactId|Generated artifact id (name of jar).| |kotlin-server| +|artifactVersion|Generated artifact's package version.| |1.0.0| +|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase| +|parcelizeModels|toggle "@Parcelize" for generated models| |null| From 031bc9c32260fc3d31fa5a819f3f492e21419f74 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Sat, 1 Jun 2019 23:51:08 +0800 Subject: [PATCH 08/12] add kotlin-vertx --- docs/generators.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/generators.md b/docs/generators.md index 3ca62059b7b5..b8de0c3714b9 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -91,6 +91,7 @@ The following generators are available: - [jaxrs-spec](generators/jaxrs-spec.md) - [kotlin-server](generators/kotlin-server.md) - [kotlin-spring](generators/kotlin-spring.md) + - [korlin-vertx](generators/kotlin-vertx.md) - [nodejs-server](generators/nodejs-server.md) - [php-laravel](generators/php-laravel.md) - [php-lumen](generators/php-lumen.md) From a80ef7ad1ac9af3c9021f3e04cef2524c713f348 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Mon, 8 Jul 2019 16:51:22 +0800 Subject: [PATCH 09/12] add model null safety --- .../languages/KotlinVertxServerCodegen.java | 9 +- .../kotlin-vertx-server/api.mustache | 23 ++- .../kotlin-vertx-server/apiError.mustache | 7 - .../kotlin-vertx-server/apiProxy.mustache | 154 ++++++++++++++++++ .../kotlin-vertx-server/apiVerticle.mustache | 145 ----------------- .../kotlin-vertx-server/data_class.mustache | 11 +- .../data_class_opt_var.mustache | 2 +- .../data_class_req_var.mustache | 2 +- .../kotlin-vertx-server/main.mustache | 12 +- .../kotlin-vertx-server/pom.mustache | 20 ++- 10 files changed, 217 insertions(+), 168 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache delete mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index 62e17f229de2..b601d5a3baf0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory; import java.io.File; +import java.util.Locale; public class KotlinVertxServerCodegen extends AbstractKotlinCodegen { @@ -59,8 +60,7 @@ public KotlinVertxServerCodegen() { apiTemplateFiles.clear(); apiTemplateFiles.put("api.mustache", ".kt"); - apiTemplateFiles.put("apiVerticle.mustache", "Verticle.kt"); - apiTemplateFiles.put("apiError.mustache","Error.kt"); + apiTemplateFiles.put("apiProxy.mustache", "VertxProxyHandler.kt"); apiTemplateFiles.put("main.mustache","Main.kt"); embeddedTemplateDir = templateDir = "kotlin-vertx-server"; @@ -77,4 +77,9 @@ public KotlinVertxServerCodegen() { supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); } + + @Override + public String escapeReservedWord(String name) { + return name; + } } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache index 7f0755a34c99..b551370bb08c 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -1,10 +1,16 @@ -package {{package}}; +package {{package}} {{#imports}}import {{import}} {{/imports}} import io.vertx.core.Vertx import io.vertx.core.json.JsonObject import com.github.wooyme.openapi.Response +import io.vertx.ext.web.api.OperationRequest +import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory +import io.vertx.serviceproxy.ServiceBinder +import io.vertx.ext.web.handler.CookieHandler +import io.vertx.ext.web.handler.SessionHandler +import io.vertx.ext.web.sstore.LocalSessionStore import java.util.List import java.util.Map @@ -14,7 +20,20 @@ interface {{classname}} { {{#operation}} /* {{operationId}} * {{summary}} */ - suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{^isRequired}}?{{/isRequired}},{{/allParams}}session:JsonObject?):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{^isRequired}}?{{/isRequired}},{{/allParams}}context:OperationRequest):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{/operation}} {{/operations}} + companion object { + const val address = "{{classname}}-service" + suspend fun createRouterFactory(vertx: Vertx,path:String,impl:{{classname}}): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) + ServiceBinder(vertx) + .setAddress(address) + .register({{classname}}::class.java,impl) + routerFactory.addGlobalHandler(CookieHandler.create()) + routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.mountServiceInterface({{classname}}::class.java, address) + return routerFactory + } + } } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache deleted file mode 100644 index 46f44e470e5a..000000000000 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiError.mustache +++ /dev/null @@ -1,7 +0,0 @@ -package {{package}}; - -class {{classname}}Error(val statusCode:Int,val statusMessage:String):Exception() { - companion object { - val INTERNAL_SERVER_ERROR = {{classname}}Error(500, "Internal Server Error") - } -} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache new file mode 100644 index 000000000000..ea537527d46b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache @@ -0,0 +1,154 @@ +package {{package}} + +import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message +import io.vertx.core.json.JsonObject +import io.vertx.ext.web.api.OperationRequest +import io.vertx.ext.web.api.OperationResponse +import io.vertx.ext.web.api.generator.ApiHandlerUtils +import io.vertx.serviceproxy.ProxyHandler +import io.vertx.serviceproxy.ServiceException +import io.vertx.serviceproxy.ServiceExceptionMessageCodec +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import io.vertx.kotlin.coroutines.dispatcher +import io.vertx.core.json.Json +import com.google.gson.Gson +{{#imports}}import {{import}} +{{/imports}} + +class {{classname}}VertxProxyHandler(private val vertx: Vertx, private val service: {{classname}}, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { + private val timerID: Long + private var lastAccessed: Long = 0 + init { + try { + this.vertx.eventBus().registerDefaultCodec(ServiceException::class.java, + ServiceExceptionMessageCodec()) + } catch (ex: IllegalStateException) {} + + if (timeoutSeconds != (-1).toLong() && !topLevel) { + var period = timeoutSeconds * 1000 / 2 + if (period > 10000) { + period = 10000 + } + this.timerID = vertx.setPeriodic(period) { this.checkTimedOut(it) } + } else { + this.timerID = -1 + } + accessed() + } + private fun checkTimedOut(id: Long) { + val now = System.nanoTime() + if (now - lastAccessed > timeoutSeconds * 1000000000) { + close() + } + } + + override fun close() { + if (timerID != (-1).toLong()) { + vertx.cancelTimer(timerID) + } + super.close() + } + + private fun accessed() { + this.lastAccessed = System.nanoTime() + } + override fun handle(msg: Message) { + try { + val json = msg.body() + val action = msg.headers().get("action") ?: throw IllegalStateException("action not specified") + accessed() + val contextSerialized = json.getJsonObject("context") ?: throw IllegalStateException("Received action $action without OperationRequest \"context\"") + val context = OperationRequest(contextSerialized) + when (action) { + {{#operations}}{{#operation}} + "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}" -> { + {{#hasParams}} + val params = context.params + {{#allParams}} + {{#isListContainer}} + val {{paramName}}Param = ApiHandlerUtils.searchJsonArrayInJson(params,"{{#isBodyParam}}body{{/isBodyParam}}{{^isBodyParam}}{{baseName}}{{/isBodyParam}}") + {{#required}} + if({{paramName}} == null){ + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() + , object : TypeToken>(){}.type) + {{/required}} + {{^required}} + val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} + else Gson().fromJson({{paramName}}Param.encode(), + , object : TypeToken>(){}.type) + {{/required}} + {{/isListContainer}} + {{^isListContainer}} + {{#isPrimitiveType}} + val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#isString}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isString}} + {{#isNumber}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isNumber}} + {{#isLong}} + val {{paramName}} = ApiHandlerUtils.searchLongInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isLong}} + {{#isInteger}} + val {{paramName}} = ApiHandlerUtils.searchIntegerInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isInteger}} + {{#isFloat}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toFloat() + {{/isFloat}} + {{#isDouble}} + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isDouble}} + {{#isBoolean}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toBoolean() + {{/isBoolean}} + {{#isFreeFormObject}} + val {{paramName}} = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isFreeFormObject}} + {{#required}} + if({{paramName}} == null){ + throw IllegalArgumentException("{{paramName}} is required") + } + {{/required}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + val {{paramName}}Param = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{#required}} + if ({{paramName}}Param == null) { + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} + {{^required}} + val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + {{/required}} + {{/isPrimitiveType}} + {{/isListContainer}} + {{/allParams}} + GlobalScope.launch(vertx.dispatcher()){ + val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}},{{/allParams}}{{/hasParams}}context) + {{#isListContainer}} + val payload = JsonArray(Json.encode(result.payload)).toBuffer() + {{/isListContainer}} + {{^isListContainer}} + val payload = JsonObject(Json.encode(result.payload)).toBuffer() + {{/isListContainer}} + val res = OperationResponse(result.statusCode,result.statusMessage,payload,result.headers) + msg.reply(res.toJson()) + }.invokeOnCompletion{ + it?.let{ throw it } + } + {{/hasParams}} + } + {{/operation}}{{/operations}} + } + }catch (t: Throwable) { + msg.reply(ServiceException(500, t.message)) + throw t + } + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache deleted file mode 100644 index 98eb78d9f7f5..000000000000 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiVerticle.mustache +++ /dev/null @@ -1,145 +0,0 @@ -package {{package}} - -import io.vertx.core.AbstractVerticle -import io.vertx.core.eventbus.Message -import io.vertx.core.json.Json -import io.vertx.core.json.JsonArray -import io.vertx.core.json.JsonObject -import com.google.gson.Gson -import io.vertx.core.logging.Logger -import io.vertx.core.logging.LoggerFactory -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import io.vertx.kotlin.coroutines.dispatcher -import com.github.wooyme.openapi.SwaggerRouter -import io.swagger.parser.OpenAPIParser -import io.swagger.v3.oas.models.OpenAPI -import io.vertx.core.Vertx -import io.vertx.ext.web.Router -import java.nio.charset.Charset -import com.github.wooyme.openapi.Response - -{{#imports}}import {{import}} -{{/imports}} - -class {{classname}}Verticle(private val service:{{classname}}):AbstractVerticle() { - companion object { - fun register(vertx:Vertx,file:String,router:Router) { - val vertxFileSystem = vertx.fileSystem() - val authBuffer = vertxFileSystem.readFileBlocking(file) - val result = OpenAPIParser().readContents(authBuffer.toString(Charset.forName("utf-8")), null, null).openAPI - SwaggerRouter.swaggerRouter(router, result, vertx.eventBus()) - } - } - private val logger = LoggerFactory.getLogger(this::class.java) - - override fun start() { - super.start() - service.init(vertx,config()) - {{#operations}}{{#operation}} - //Consumer for {{#vendorExtensions}}{{operationId}}{{/vendorExtensions}} - vertx.eventBus().consumer({{#vendorExtensions}}"{{operationId}}"{{/vendorExtensions}}).handler { message-> - try{ - val serviceId = "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}" - {{#hasParams}} - {{#allParams}} - {{#isListContainer}} - val {{paramName}}Param = message.body().getJsonArray("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") - {{#required}} - if({{paramName}}Param == null) { - manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) - return@handler - } - val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() - , object : TypeToken>(){}.type) - {{/required}} - {{^required}} - val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} - else Gson().fromJson({{paramName}}Param.encode(), - , object : TypeToken>(){}.type) - {{/required}} - {{/isListContainer}} - {{^isListContainer}} - {{#isPrimitiveType}} - val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") - {{#required}} - if({{paramName}}Param == null) { - manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) - return@handler - } - {{/required}} - {{#isString}} - val {{paramName}} = {{paramName}}Param - {{/isString}} - {{#isNumber}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toBigDecimal() - {{/isNumber}} - {{#isLong}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toLong() - {{/isLong}} - {{#isInteger}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toInt() - {{/isInteger}} - {{#isFloat}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toFloat() - {{/isFloat}} - {{#isDouble}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toDouble() - {{/isDouble}} - {{#isBoolean}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.toBoolean() - {{/isBoolean}} - {{#isFreeFormObject}} - val {{paramName}} = {{paramName}}Param{{^required}}?{{/required}}.let{ try { JsonObject({{paramName}}Param) }catch( e:Exception ){ {{paramName}}Param } } - {{/isFreeFormObject}} - {{/isPrimitiveType}} - {{^isPrimitiveType}} - val {{paramName}}Param = message.body().getJsonObject("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") - {{#required}} - if ({{paramName}}Param == null) { - manageError(message, {{classname}}Error(400, "{{baseName}} is required"), serviceId) - return@handler - } - val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) - {{/required}} - {{^required}} - val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) - {{/required}} - {{/isPrimitiveType}} - {{/isListContainer}} - {{/allParams}} - {{/hasParams}} - val session = message.body().getJsonObject("session") - GlobalScope.launch(vertx.dispatcher()){ - val result = service.{{operationId}}({{#hasParams}}{{#allParams}}{{paramName}},{{/allParams}}{{/hasParams}}session) - val json = JsonObject() - if(result.session!=null){ - json.put("session",result.session) - } - {{#returnType}} - json.put("body",Json.encode(result.body)) - {{/returnType}} - message.reply(json) - }.invokeOnCompletion { - if(it!=null) manageError(message, it, "{{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}") - } - }catch(e:Exception){ - logger.error("Unexpected error in {{#vendorExtensions}}{{operationId}}{{/vendorExtensions}}",e) - } - } - {{/operation}}{{/operations}} - - } - - private fun manageError(message: Message, cause: Throwable, serviceName: String) { - var code = {{classname}}Error.INTERNAL_SERVER_ERROR.statusCode - var statusMessage = {{classname}}Error.INTERNAL_SERVER_ERROR.statusMessage - if (cause is {{classname}}Error) { - code = cause.statusCode - statusMessage = cause.statusMessage - } else { - logger.error(serviceName, cause) - } - message.fail(code, statusMessage) - } -} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache index feb6a0b317e6..d4c099d64ea7 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class.mustache @@ -1,8 +1,11 @@ + {{#parcelizeModels}} import android.os.Parcelable import kotlinx.android.parcel.Parcelize - {{/parcelizeModels}} +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude /** * {{{description}}} {{#vars}} @@ -12,6 +15,8 @@ import kotlinx.android.parcel.Parcelize {{#parcelizeModels}} @Parcelize {{/parcelizeModels}} +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) data class {{classname}} ( {{#requiredVars}} {{>data_class_req_var}}{{^-last}}, @@ -30,4 +35,8 @@ data class {{classname}} ( {{/enumVars}}{{/allowableValues}} } {{/isEnum}}{{/vars}}{{/hasEnums}} + {{#requiredVars}} + var {{{name}}} get() = _{{{name}}} ?: throw IllegalArgumentException("{{{name}}} is required") + set(value){ _{{{name}}} = value } + {{/requiredVars}} } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache index 8bcc20d0fcac..809b00758683 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_opt_var.mustache @@ -1,4 +1,4 @@ {{#description}} /* {{{description}}} */ {{/description}} - val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}} \ No newline at end of file + var {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache index f8ffa6cde827..66ec56120bea 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/data_class_req_var.mustache @@ -1,4 +1,4 @@ {{#description}} /* {{{description}}} */ {{/description}} - val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}} \ No newline at end of file + @SerializedName("{{{name}}}") private var _{{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache index dfb4deb3d307..cdd2bbd731e2 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache @@ -6,16 +6,12 @@ import io.vertx.ext.web.handler.BodyHandler import io.vertx.ext.web.handler.SessionHandler import io.vertx.ext.web.sstore.SessionStore -fun main(args:Array){ +suspend fun main(args:Array){ val vertx = Vertx.vertx() val httpServer = vertx.createHttpServer() - val router = Router.router(vertx) - router.route().handler(BodyHandler.create()) - router.route().handler(SessionHandler.create(SessionStore.create(vertx))) - {{classname}}Verticle.register(vertx,if(args.size>1) args[1] else "openapi.json",router) - //vertx.deployVerticle(DefaultApiVerticle(DefaultApiImpl(...))) - httpServer.requestHandler(router).listen(80){ + val router = DocApi.createRouterFactory(vertx,"",DocApi::class.java.newInstance()).router + httpServer.requestHandler(router).listen(8080){ if(it.failed()) it.cause().printStackTrace() - else println("Listen at 80 !") + else println("Listen at 8080 !") } } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache index a0d13ba26c68..6c8a338789a3 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache @@ -17,7 +17,7 @@ 4.12 3.4.1 3.3 - 1.0.1 + 1.0.2 2.3 2.7.4 3.6.0 @@ -95,6 +95,24 @@ 2.0.5 + + io.vertx + vertx-web-api-contract + ${vertx.version} + + + + io.vertx + vertx-service-proxy + ${vertx.version} + + + + io.vertx + vertx-web-api-service + ${vertx.version} + + From e49776f8f5782700854b3eba04e6028baa2c96e8 Mon Sep 17 00:00:00 2001 From: wooyme <867653608@qq.com> Date: Tue, 9 Jul 2019 09:51:38 +0800 Subject: [PATCH 10/12] change to vert.x offical web api --- .../languages/KotlinVertxServerCodegen.java | 2 +- .../resources/kotlin-vertx-server/api.mustache | 17 +++++++++++++---- .../kotlin-vertx-server/api_verticle.mustache | 16 ++++++++++++++++ .../resources/kotlin-vertx-server/main.mustache | 17 ----------------- 4 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache delete mode 100644 modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java index b601d5a3baf0..19863e9a67b8 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinVertxServerCodegen.java @@ -61,7 +61,7 @@ public KotlinVertxServerCodegen() { apiTemplateFiles.clear(); apiTemplateFiles.put("api.mustache", ".kt"); apiTemplateFiles.put("apiProxy.mustache", "VertxProxyHandler.kt"); - apiTemplateFiles.put("main.mustache","Main.kt"); + apiTemplateFiles.put("api_verticle.mustache","Verticle.kt"); embeddedTemplateDir = templateDir = "kotlin-vertx-server"; apiPackage = rootPackage + ".verticle"; diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache index b551370bb08c..ca27e1c4fdf9 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -25,13 +25,22 @@ interface {{classname}} { {{/operations}} companion object { const val address = "{{classname}}-service" - suspend fun createRouterFactory(vertx: Vertx,path:String,impl:{{classname}}): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { + suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) - ServiceBinder(vertx) - .setAddress(address) - .register({{classname}}::class.java,impl) routerFactory.addGlobalHandler(CookieHandler.create()) routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + val opf = routerFactory::class.java.getDeclaredField("operations") + opf.isAccessible = true + val operations = opf.get(routerFactory) as Map + for (m in {{classname}}::class.java.methods) { + val methodName = m.name + val op = operations[methodName] + if (op != null) { + val method = op::class.java.getDeclaredMethod("mountRouteToService",String::class.java,String::class.java) + method.isAccessible = true + method.invoke(op,address,methodName) + } + } routerFactory.mountServiceInterface({{classname}}::class.java, address) return routerFactory } diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache new file mode 100644 index 000000000000..2c16c11c7a92 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache @@ -0,0 +1,16 @@ +package {{package}} + +import io.vertx.core.AbstractVerticle +import io.vertx.serviceproxy.ServiceBinder + + +class {{classname}}Verticle:AbstractVerticle() { + + override fun start() { + val instance = (javaClass.classLoader.loadClass("{{package}}.{{classname}}Impl").newInstance() as {{classname}}) + instance.init(vertx,config()) + ServiceBinder(vertx) + .setAddress({{classname}}.address) + .register({{classname}}::class.java,instance) + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache deleted file mode 100644 index cdd2bbd731e2..000000000000 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/main.mustache +++ /dev/null @@ -1,17 +0,0 @@ -package {{package}} - -import io.vertx.core.Vertx -import io.vertx.ext.web.Router -import io.vertx.ext.web.handler.BodyHandler -import io.vertx.ext.web.handler.SessionHandler -import io.vertx.ext.web.sstore.SessionStore - -suspend fun main(args:Array){ - val vertx = Vertx.vertx() - val httpServer = vertx.createHttpServer() - val router = DocApi.createRouterFactory(vertx,"",DocApi::class.java.newInstance()).router - httpServer.requestHandler(router).listen(8080){ - if(it.failed()) it.cause().printStackTrace() - else println("Listen at 8080 !") - } -} \ No newline at end of file From d923efac80889e09c4e496481aeed62cf607c4d2 Mon Sep 17 00:00:00 2001 From: Wooyme <867653608@qq.com> Date: Sun, 11 Aug 2019 21:38:00 +0800 Subject: [PATCH 11/12] fix date and datetime missing --- .../kotlin-vertx-server/apiProxy.mustache | 59 +++++++++++-------- .../kotlin-vertx-server/api_verticle.mustache | 5 +- .../kotlin-vertx-server/pom.mustache | 2 +- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache index ea537527d46b..2a1e04e9e7aa 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache @@ -68,63 +68,74 @@ class {{classname}}VertxProxyHandler(private val vertx: Vertx, private val servi val params = context.params {{#allParams}} {{#isListContainer}} - val {{paramName}}Param = ApiHandlerUtils.searchJsonArrayInJson(params,"{{#isBodyParam}}body{{/isBodyParam}}{{^isBodyParam}}{{baseName}}{{/isBodyParam}}") + val {{paramName}}Param = ApiHandlerUtils.searchJsonArrayInJson(params,"{{#isBodyParam}}body{{/isBodyParam}}{{^isBodyParam}}{{baseName}}{{/isBodyParam}}") {{#required}} - if({{paramName}} == null){ - throw IllegalArgumentException("{{paramName}} is required") - } - val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() + if({{paramName}} == null){ + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() , object : TypeToken>(){}.type) {{/required}} {{^required}} - val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} + val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else Gson().fromJson({{paramName}}Param.encode(), , object : TypeToken>(){}.type) {{/required}} {{/isListContainer}} {{^isListContainer}} {{#isPrimitiveType}} - val {{paramName}}Param = message.body().getString("{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{#isString}} - val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isString}} + {{#isDate}} + val {{paramName}} = java.time.LocalDate.parse(ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")) + {{/isDate}} + {{#isDateTime}} + val {{paramName}} = java.time.LocalDateTime.parse(ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")) + {{/isDateTime}} + {{#isEmail}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isEmail}} + {{#isUuid}} + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + {{/isUuid}} {{#isNumber}} - val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isNumber}} {{#isLong}} - val {{paramName}} = ApiHandlerUtils.searchLongInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchLongInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isLong}} {{#isInteger}} - val {{paramName}} = ApiHandlerUtils.searchIntegerInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchIntegerInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isInteger}} {{#isFloat}} - val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toFloat() + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toFloat() {{/isFloat}} {{#isDouble}} - val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchDoubleInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isDouble}} {{#isBoolean}} - val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toBoolean() + val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}")?.toBoolean() {{/isBoolean}} {{#isFreeFormObject}} - val {{paramName}} = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}} = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{/isFreeFormObject}} {{#required}} - if({{paramName}} == null){ - throw IllegalArgumentException("{{paramName}} is required") - } + if({{paramName}} == null){ + throw IllegalArgumentException("{{paramName}} is required") + } {{/required}} {{/isPrimitiveType}} {{^isPrimitiveType}} - val {{paramName}}Param = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") + val {{paramName}}Param = ApiHandlerUtils.searchJsonObjectInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") {{#required}} - if ({{paramName}}Param == null) { - throw IllegalArgumentException("{{paramName}} is required") - } - val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + if ({{paramName}}Param == null) { + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}} = Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) {{/required}} {{^required}} - val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) + val {{paramName}} = if({{paramName}}Param ==null) null else Gson().fromJson({{paramName}}Param.encode(), {{{dataType}}}::class.java) {{/required}} {{/isPrimitiveType}} {{/isListContainer}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache index 2c16c11c7a92..c168d12e03a3 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api_verticle.mustache @@ -1,8 +1,11 @@ package {{package}} - +import io.vertx.core.Vertx import io.vertx.core.AbstractVerticle import io.vertx.serviceproxy.ServiceBinder +fun main(){ + Vertx.vertx().deployVerticle({{classname}}Verticle()) +} class {{classname}}Verticle:AbstractVerticle() { diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache index 6c8a338789a3..08a7b3496ab3 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/pom.mustache @@ -175,7 +175,7 @@ - {{apiPackage}}.DefaultApiMainKt + {{apiPackage}}.DefaultApiVerticleKt From bfee5b877a23df358f02691e7969cf94d9623b82 Mon Sep 17 00:00:00 2001 From: Wooyme <867653608@qq.com> Date: Wed, 14 Aug 2019 21:42:16 +0800 Subject: [PATCH 12/12] fix fileupload --- .../kotlin-vertx-server/api.mustache | 7 +++++- .../kotlin-vertx-server/apiProxy.mustache | 22 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache index ca27e1c4fdf9..279271960743 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/api.mustache @@ -4,6 +4,7 @@ package {{package}} {{/imports}} import io.vertx.core.Vertx import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray import com.github.wooyme.openapi.Response import io.vertx.ext.web.api.OperationRequest import io.vertx.kotlin.ext.web.api.contract.openapi3.OpenAPI3RouterFactory @@ -14,13 +15,14 @@ import io.vertx.ext.web.sstore.LocalSessionStore import java.util.List import java.util.Map + interface {{classname}} { fun init(vertx:Vertx,config:JsonObject) {{#operations}} {{#operation}} /* {{operationId}} * {{summary}} */ - suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{{dataType}}}{{^isRequired}}?{{/isRequired}},{{/allParams}}context:OperationRequest):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + suspend fun {{operationId}}({{#allParams}}{{paramName}}:{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}kotlin.collections.List{{/isFile}}{{^isRequired}}?{{/isRequired}},{{/allParams}}context:OperationRequest):Response<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{/operation}} {{/operations}} companion object { @@ -29,6 +31,9 @@ interface {{classname}} { val routerFactory = OpenAPI3RouterFactory.createAwait(vertx,path) routerFactory.addGlobalHandler(CookieHandler.create()) routerFactory.addGlobalHandler(SessionHandler.create(LocalSessionStore.create(vertx))) + routerFactory.setExtraOperationContextPayloadMapper{ + JsonObject().put("files",JsonArray(it.fileUploads().map { it.uploadedFileName() })) + } val opf = routerFactory::class.java.getDeclaredField("operations") opf.isAccessible = true val operations = opf.get(routerFactory) as Map diff --git a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache index 2a1e04e9e7aa..8c6f81f1b43f 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-vertx-server/apiProxy.mustache @@ -13,6 +13,8 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import io.vertx.kotlin.coroutines.dispatcher import io.vertx.core.json.Json +import io.vertx.core.json.JsonArray +import com.google.gson.reflect.TypeToken import com.google.gson.Gson {{#imports}}import {{import}} {{/imports}} @@ -70,19 +72,31 @@ class {{classname}}VertxProxyHandler(private val vertx: Vertx, private val servi {{#isListContainer}} val {{paramName}}Param = ApiHandlerUtils.searchJsonArrayInJson(params,"{{#isBodyParam}}body{{/isBodyParam}}{{^isBodyParam}}{{baseName}}{{/isBodyParam}}") {{#required}} - if({{paramName}} == null){ + if({{paramName}}Param == null){ throw IllegalArgumentException("{{paramName}} is required") } val {{paramName}}:{{{dataType}}} = Gson().fromJson({{paramName}}Param.encode() - , object : TypeToken>(){}.type) + , object : TypeToken>(){}.type) {{/required}} {{^required}} val {{paramName}}:{{{dataType}}}? = if({{paramName}}Param == null) {{#defaultValue}}{{defaultValue}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}} else Gson().fromJson({{paramName}}Param.encode(), - , object : TypeToken>(){}.type) + , object : TypeToken>(){}.type) {{/required}} {{/isListContainer}} {{^isListContainer}} + {{#isFile}} + val {{paramName}}Param = context.extra.getJsonArray("files") + {{#required}} + if ({{paramName}}Param == null) { + throw IllegalArgumentException("{{paramName}} is required") + } + val {{paramName}} = {{paramName}}Param.map{ java.io.File(it as String) } + {{/required}} + {{^required}} + val {{paramName}} = {{paramName}}Param?.map{ java.io.File(it as String) } + {{/required}} + {{/isFile}} {{#isPrimitiveType}} {{#isString}} val {{paramName}} = ApiHandlerUtils.searchStringInJson(params,"{{^isBodyParam}}{{baseName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}") @@ -162,4 +176,4 @@ class {{classname}}VertxProxyHandler(private val vertx: Vertx, private val servi throw t } } -} \ No newline at end of file +}