From b13c3ee46fd9c7fae185b36b22032f83fee77809 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 14 Nov 2019 20:37:47 +0100 Subject: [PATCH 01/17] bump jackson to 2.10.1 --- pom.xml | 4 ++-- .../v3/generators/java/JavaClientCodegen.java | 6 +++--- .../handlebars/Java/build.gradle.mustache | 2 +- .../Java/libraries/feign/build.gradle.mustache | 2 +- .../Java/libraries/feign/build.sbt.mustache | 8 ++++---- .../Java/libraries/feign/pom.mustache | 2 +- .../libraries/jersey2/build.gradle.mustache | 4 ++-- .../Java/libraries/jersey2/build.sbt.mustache | 17 +++++++++-------- .../Java/libraries/jersey2/pom.mustache | 9 +++++++-- src/main/resources/handlebars/Java/pom.mustache | 2 +- .../JavaJaxRS/resteasy/eap/gradle.mustache | 4 ++-- .../JavaJaxRS/resteasy/eap/pom.mustache | 12 ++++++------ .../JavaJaxRS/resteasy/gradle.mustache | 4 ++-- .../handlebars/JavaJaxRS/resteasy/pom.mustache | 4 ++-- .../mustache/Java/build.gradle.mustache | 2 +- .../Java/libraries/feign/build.gradle.mustache | 2 +- .../Java/libraries/feign/build.sbt.mustache | 8 ++++---- .../mustache/Java/libraries/feign/pom.mustache | 2 +- .../libraries/google-api-client/api.mustache | 4 ++-- .../google-api-client/build.gradle.mustache | 2 +- .../google-api-client/build.sbt.mustache | 14 +++++++------- .../libraries/google-api-client/pom.mustache | 4 ++-- .../libraries/jersey2/build.gradle.mustache | 2 +- .../Java/libraries/jersey2/build.sbt.mustache | 17 +++++++++-------- .../Java/libraries/jersey2/pom.mustache | 9 +++++++-- .../Java/libraries/vertx/ApiClient.mustache | 2 +- src/main/resources/mustache/Java/pom.mustache | 2 +- .../JavaJaxRS/resteasy/eap/gradle.mustache | 4 ++-- .../JavaJaxRS/resteasy/eap/pom.mustache | 12 ++++++------ 29 files changed, 89 insertions(+), 77 deletions(-) diff --git a/pom.xml b/pom.xml index a48dac44e7..a587ac7c71 100644 --- a/pom.xml +++ b/pom.xml @@ -248,8 +248,8 @@ 3.0.14-SNAPSHOT 2.0.16-SNAPSHOT - 2.0.10 - 2.9.10 + 2.0.11-SNAPSHOT + 2.10.1 2.11.1 3.3.0 2.4 diff --git a/src/main/java/io/swagger/codegen/v3/generators/java/JavaClientCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/java/JavaClientCodegen.java index aa4e6c22cf..af14e461c4 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/java/JavaClientCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/java/JavaClientCodegen.java @@ -83,9 +83,9 @@ public JavaClientCodegen() { cliOptions.add(CliOption.newBoolean(USE_GZIP_FEATURE, "Send gzip-encoded requests")); cliOptions.add(CliOption.newBoolean(USE_RUNTIME_EXCEPTION, "Use RuntimeException instead of Exception")); - supportedLibraries.put("jersey1", "HTTP client: Jersey client 1.19.4. JSON processing: Jackson 2.9.10. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'."); - supportedLibraries.put("feign", "HTTP client: OpenFeign 9.4.0. JSON processing: Jackson 2.9.10"); - supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.9.10"); + supportedLibraries.put("jersey1", "HTTP client: Jersey client 1.19.4. JSON processing: Jackson 2.10.1. Enable Java6 support using '-DsupportJava6=true'. Enable gzip request encoding using '-DuseGzipFeature=true'."); + supportedLibraries.put("feign", "HTTP client: OpenFeign 9.4.0. JSON processing: Jackson 2.10.1"); + supportedLibraries.put("jersey2", "HTTP client: Jersey client 2.26. JSON processing: Jackson 2.10.1"); supportedLibraries.put("okhttp-gson", "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.8.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'."); supportedLibraries.put(RETROFIT_1, "HTTP client: OkHttp 2.7.5. JSON processing: Gson 2.3.1 (Retrofit 1.9.0). IMPORTANT NOTE: retrofit1.x is no longer actively maintained so please upgrade to 'retrofit2' instead."); supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 3.8.0. JSON processing: Gson 2.6.1 (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2]=true'. (RxJava 1.x or 2.x)"); diff --git a/src/main/resources/handlebars/Java/build.gradle.mustache b/src/main/resources/handlebars/Java/build.gradle.mustache index 06f58d52a6..8ea8389223 100644 --- a/src/main/resources/handlebars/Java/build.gradle.mustache +++ b/src/main/resources/handlebars/Java/build.gradle.mustache @@ -112,7 +112,7 @@ ext { {{^useOas2}} swagger_annotations_version = "2.0.0" {{/useOas2}} - jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/src/main/resources/handlebars/Java/libraries/feign/build.gradle.mustache b/src/main/resources/handlebars/Java/libraries/feign/build.gradle.mustache index 79b16f5106..07b70c841d 100644 --- a/src/main/resources/handlebars/Java/libraries/feign/build.gradle.mustache +++ b/src/main/resources/handlebars/Java/libraries/feign/build.gradle.mustache @@ -106,7 +106,7 @@ ext { {{^useOas2}} swagger_annotations_version = "2.0.0" {{/useOas2}} - jackson_version = "2.9.10" + jackson_version = "2.10.1" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} diff --git a/src/main/resources/handlebars/Java/libraries/feign/build.sbt.mustache b/src/main/resources/handlebars/Java/libraries/feign/build.sbt.mustache index a466841c47..7230311c3d 100644 --- a/src/main/resources/handlebars/Java/libraries/feign/build.sbt.mustache +++ b/src/main/resources/handlebars/Java/libraries/feign/build.sbt.mustache @@ -19,10 +19,10 @@ lazy val root = (project in file(".")). "com.netflix.feign" % "feign-jackson" % "9.4.0" % "compile", "com.netflix.feign" % "feign-slf4j" % "9.4.0" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", - "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.10.1" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.2" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/src/main/resources/handlebars/Java/libraries/feign/pom.mustache b/src/main/resources/handlebars/Java/libraries/feign/pom.mustache index 362fd5da0b..86be3068b6 100644 --- a/src/main/resources/handlebars/Java/libraries/feign/pom.mustache +++ b/src/main/resources/handlebars/Java/libraries/feign/pom.mustache @@ -290,7 +290,7 @@ {{/useOas2}} 9.4.0 2.1.0 - 2.9.10 + 2.10.1 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache b/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache index 2574f9a69c..f21044a155 100644 --- a/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache +++ b/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache @@ -111,8 +111,8 @@ ext { {{^useOas2}} swagger_annotations_version = "2.0.0" {{/useOas2}} - jackson_version = "2.9.10" - jersey_version = "2.25.1" + jackson_version = "2.10.1" + jersey_version = "2.26" {{#supportJava6}} commons_io_version=2.5 commons_lang3_version=3.6 diff --git a/src/main/resources/handlebars/Java/libraries/jersey2/build.sbt.mustache b/src/main/resources/handlebars/Java/libraries/jersey2/build.sbt.mustache index b0a6298e95..5c9a87d31a 100644 --- a/src/main/resources/handlebars/Java/libraries/jersey2/build.sbt.mustache +++ b/src/main/resources/handlebars/Java/libraries/jersey2/build.sbt.mustache @@ -15,17 +15,18 @@ lazy val root = (project in file(".")). {{^useOas2}} "io.swagger.core.v3" % "swagger-annotations" % "2.0.0", {{/useOas2}} - "org.glassfish.jersey.core" % "jersey-client" % "2.25.1", - "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.25.1", - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "org.glassfish.jersey.core" % "jersey-client" % "2.29.1", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.29.1", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.29.1", + "org.glassfish.jersey.inject" % "jersey-hk2" % "2.29.1", + "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.1" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.1" % "compile", {{/java8}} {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", diff --git a/src/main/resources/handlebars/Java/libraries/jersey2/pom.mustache b/src/main/resources/handlebars/Java/libraries/jersey2/pom.mustache index 8414d5c013..5fe4033d63 100644 --- a/src/main/resources/handlebars/Java/libraries/jersey2/pom.mustache +++ b/src/main/resources/handlebars/Java/libraries/jersey2/pom.mustache @@ -214,6 +214,11 @@ jersey-media-json-jackson ${jersey-version} + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey-version} + @@ -307,14 +312,14 @@ 2.0.0 {{/useOas2}} {{^supportJava6}} - 2.25.1 + 2.29.1 {{/supportJava6}} {{#supportJava6}} 2.6 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 4.12 diff --git a/src/main/resources/handlebars/Java/pom.mustache b/src/main/resources/handlebars/Java/pom.mustache index a821e48810..c37b52281d 100644 --- a/src/main/resources/handlebars/Java/pom.mustache +++ b/src/main/resources/handlebars/Java/pom.mustache @@ -322,7 +322,7 @@ 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 4.12 diff --git a/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/gradle.mustache b/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/gradle.mustache index 63c6384938..069226075d 100644 --- a/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/gradle.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/gradle.mustache @@ -19,11 +19,11 @@ dependencies { providedCompile 'javax.validation:validation-api:1.1.0.Final' {{/useBeanValidation}} {{^java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.10.1' compile 'joda-time:joda-time:2.7' {{/java8}} {{#java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1' {{/java8}} testCompile 'junit:junit:4.12', 'org.hamcrest:hamcrest-core:1.3' diff --git a/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/pom.mustache b/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/pom.mustache index 91ecdd5e08..7f09021c2a 100644 --- a/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/pom.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/resteasy/eap/pom.mustache @@ -195,30 +195,30 @@ com.fasterxml.jackson.datatype jackson-datatype-joda - 2.9.10 + 2.10.1 {{/java8}} {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.9.10 + 2.10.1 {{/java8}} com.fasterxml.jackson.core jackson-databind - 2.9.10 + 2.10.1 com.fasterxml.jackson.core jackson-core - 2.9.10 + 2.10.1 com.fasterxml.jackson.core jackson-annotations - 2.9.10 + 2.10.1 org.apache.httpcomponents @@ -244,7 +244,7 @@ {{^useOas2}} 2.0.0 {{/useOas2}} - 9.2.9.v20150224 + 9.3.27.v20190418 3.0.11.Final 1.6.3 4.8.1 diff --git a/src/main/resources/handlebars/JavaJaxRS/resteasy/gradle.mustache b/src/main/resources/handlebars/JavaJaxRS/resteasy/gradle.mustache index 6f9f711d4f..9e66a801d0 100644 --- a/src/main/resources/handlebars/JavaJaxRS/resteasy/gradle.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/resteasy/gradle.mustache @@ -27,11 +27,11 @@ dependencies { providedCompile 'javax.validation:validation-api:1.1.0.Final' {{/useBeanValidation}} {{^java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.10.1' compile 'joda-time:joda-time:2.7' {{/java8}} {{#java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1' {{/java8}} //TODO: swaggerFeature {{#useOas2}} diff --git a/src/main/resources/handlebars/JavaJaxRS/resteasy/pom.mustache b/src/main/resources/handlebars/JavaJaxRS/resteasy/pom.mustache index 3610b9170b..e15562edf1 100644 --- a/src/main/resources/handlebars/JavaJaxRS/resteasy/pom.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/resteasy/pom.mustache @@ -218,11 +218,11 @@ {{^useOas2}} 2.0.9 {{/useOas2}} - 9.2.9.v20150224 + 9.3.27.v20190418 3.0.11.Final 1.6.3 4.8.1 2.5 - {{#java8}}2.9.10{{/java8}} + {{#java8}}2.10.1{{/java8}} diff --git a/src/main/resources/mustache/Java/build.gradle.mustache b/src/main/resources/mustache/Java/build.gradle.mustache index 0918c86006..a00979fbd7 100644 --- a/src/main/resources/mustache/Java/build.gradle.mustache +++ b/src/main/resources/mustache/Java/build.gradle.mustache @@ -121,7 +121,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.17" - jackson_version = "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" + jackson_version = "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" jersey_version = "1.19.4" jodatime_version = "2.9.9" junit_version = "4.12" diff --git a/src/main/resources/mustache/Java/libraries/feign/build.gradle.mustache b/src/main/resources/mustache/Java/libraries/feign/build.gradle.mustache index f25b668772..f27554c165 100644 --- a/src/main/resources/mustache/Java/libraries/feign/build.gradle.mustache +++ b/src/main/resources/mustache/Java/libraries/feign/build.gradle.mustache @@ -101,7 +101,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.9" - jackson_version = "2.9.10" + jackson_version = "2.10.1" {{#threetenbp}} threepane_version = "2.6.4" {{/threetenbp}} diff --git a/src/main/resources/mustache/Java/libraries/feign/build.sbt.mustache b/src/main/resources/mustache/Java/libraries/feign/build.sbt.mustache index c73aaea8d5..d034b3d79e 100644 --- a/src/main/resources/mustache/Java/libraries/feign/build.sbt.mustache +++ b/src/main/resources/mustache/Java/libraries/feign/build.sbt.mustache @@ -14,10 +14,10 @@ lazy val root = (project in file(".")). "io.github.openfeign" % "feign-jackson" % "9.4.0" % "compile", "io.github.openfeign" % "feign-slf4j" % "9.4.0" % "compile", "io.github.openfeign.form" % "feign-form" % "2.1.0" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", - "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.10.1" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "junit" % "junit" % "4.12" % "test", diff --git a/src/main/resources/mustache/Java/libraries/feign/pom.mustache b/src/main/resources/mustache/Java/libraries/feign/pom.mustache index 40879438a1..522dad9d89 100644 --- a/src/main/resources/mustache/Java/libraries/feign/pom.mustache +++ b/src/main/resources/mustache/Java/libraries/feign/pom.mustache @@ -297,7 +297,7 @@ 1.5.18 9.4.0 2.1.0 - 2.9.10 + 2.10.1 {{#threetenbp}} 2.6.4 {{/threetenbp}} diff --git a/src/main/resources/mustache/Java/libraries/google-api-client/api.mustache b/src/main/resources/mustache/Java/libraries/google-api-client/api.mustache index 46ecf3af35..f14a2ed155 100644 --- a/src/main/resources/mustache/Java/libraries/google-api-client/api.mustache +++ b/src/main/resources/mustache/Java/libraries/google-api-client/api.mustache @@ -58,7 +58,7 @@ public class {{classname}} { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; - return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + return ({{{returnType}}})apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } /**{{#summary}} @@ -77,7 +77,7 @@ public class {{classname}} { public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} TypeReference typeRef = new TypeReference<{{{returnType}}}>() {}; - return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} + return ({{{returnType}}})apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { diff --git a/src/main/resources/mustache/Java/libraries/google-api-client/build.gradle.mustache b/src/main/resources/mustache/Java/libraries/google-api-client/build.gradle.mustache index 23de2e62f2..1bd086a9af 100644 --- a/src/main/resources/mustache/Java/libraries/google-api-client/build.gradle.mustache +++ b/src/main/resources/mustache/Java/libraries/google-api-client/build.gradle.mustache @@ -107,7 +107,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.17" - jackson_version = "2.9.10" + jackson_version = "2.10.1" google_api_client_version = "1.23.0" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" diff --git a/src/main/resources/mustache/Java/libraries/google-api-client/build.sbt.mustache b/src/main/resources/mustache/Java/libraries/google-api-client/build.sbt.mustache index 28987e37a5..adb175f96e 100644 --- a/src/main/resources/mustache/Java/libraries/google-api-client/build.sbt.mustache +++ b/src/main/resources/mustache/Java/libraries/google-api-client/build.sbt.mustache @@ -11,18 +11,18 @@ lazy val root = (project in file(".")). libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.17", "com.google.api-client" % "google-api-client" % "1.23.0", - "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.9.10" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10" % "compile", + "org.glassfish.jersey.core" % "jersey-common" % "2.26", + "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", {{#withXml}} - "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.10.1" % "compile", {{/withXml}} {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.1" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.1" % "compile", {{/java8}} {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.10" % "compile", diff --git a/src/main/resources/mustache/Java/libraries/google-api-client/pom.mustache b/src/main/resources/mustache/Java/libraries/google-api-client/pom.mustache index 8d32465494..aa444ef133 100644 --- a/src/main/resources/mustache/Java/libraries/google-api-client/pom.mustache +++ b/src/main/resources/mustache/Java/libraries/google-api-client/pom.mustache @@ -285,8 +285,8 @@ UTF-8 1.5.17 1.23.0 - 2.25.1 - 2.9.10 + 2.26 + 2.10.1 {{#joda}} 2.9.9 {{/joda}} diff --git a/src/main/resources/mustache/Java/libraries/jersey2/build.gradle.mustache b/src/main/resources/mustache/Java/libraries/jersey2/build.gradle.mustache index 61bce0d245..3dfae528c0 100644 --- a/src/main/resources/mustache/Java/libraries/jersey2/build.gradle.mustache +++ b/src/main/resources/mustache/Java/libraries/jersey2/build.gradle.mustache @@ -106,7 +106,7 @@ if(hasProperty('target') && target == 'android') { ext { swagger_annotations_version = "1.5.17" - jackson_version = "2.9.10" + jackson_version = "2.10.1" {{#supportJava6}} jersey_version = "2.6" commons_io_version=2.5 diff --git a/src/main/resources/mustache/Java/libraries/jersey2/build.sbt.mustache b/src/main/resources/mustache/Java/libraries/jersey2/build.sbt.mustache index 32ada4a514..4d11185be2 100644 --- a/src/main/resources/mustache/Java/libraries/jersey2/build.sbt.mustache +++ b/src/main/resources/mustache/Java/libraries/jersey2/build.sbt.mustache @@ -10,17 +10,18 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.17", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.29.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.29.1"{{/supportJava6}}, + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.29.1"{{/supportJava6}}, + {{^supportJava6}}"org.glassfish.jersey.inject" % "jersey-hk2" % "2.29.1",{{/supportJava6}} + "com.fasterxml.jackson.core" % "jackson-core" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "{{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}}" % "compile", {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.1" % "compile", {{/joda}} {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.1" % "compile", {{/java8}} {{#threetenbp}} "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.6.4" % "compile", diff --git a/src/main/resources/mustache/Java/libraries/jersey2/pom.mustache b/src/main/resources/mustache/Java/libraries/jersey2/pom.mustache index cb8cc23b8c..a5547b735f 100644 --- a/src/main/resources/mustache/Java/libraries/jersey2/pom.mustache +++ b/src/main/resources/mustache/Java/libraries/jersey2/pom.mustache @@ -228,6 +228,11 @@ ${jersey-version} + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey-version} + com.fasterxml.jackson.core @@ -316,14 +321,14 @@ UTF-8 1.5.18 {{^supportJava6}} - 2.25.1 + 2.29.1 {{/supportJava6}} {{#supportJava6}} 2.6 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 4.12 diff --git a/src/main/resources/mustache/Java/libraries/vertx/ApiClient.mustache b/src/main/resources/mustache/Java/libraries/vertx/ApiClient.mustache index 1de56ec9ca..fa9dbfd900 100644 --- a/src/main/resources/mustache/Java/libraries/vertx/ApiClient.mustache +++ b/src/main/resources/mustache/Java/libraries/vertx/ApiClient.mustache @@ -553,7 +553,7 @@ public class ApiClient { handleFileDownload(httpResponse, handler); return; } else { - resultContent = Json.decodeValue(httpResponse.body(), returnType); + resultContent = (T) Json.decodeValue(httpResponse.body(), returnType); } result = Future.succeededFuture(resultContent); } diff --git a/src/main/resources/mustache/Java/pom.mustache b/src/main/resources/mustache/Java/pom.mustache index 3b5fbacb51..58b8d4bce2 100644 --- a/src/main/resources/mustache/Java/pom.mustache +++ b/src/main/resources/mustache/Java/pom.mustache @@ -329,7 +329,7 @@ 2.5 3.6 {{/supportJava6}} - {{^threetenbp}}2.9.10{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} + {{^threetenbp}}2.10.1{{/threetenbp}}{{#threetenbp}}2.6.4{{/threetenbp}} 1.0.0 4.12 diff --git a/src/main/resources/mustache/JavaJaxRS/resteasy/eap/gradle.mustache b/src/main/resources/mustache/JavaJaxRS/resteasy/eap/gradle.mustache index 63c6384938..069226075d 100644 --- a/src/main/resources/mustache/JavaJaxRS/resteasy/eap/gradle.mustache +++ b/src/main/resources/mustache/JavaJaxRS/resteasy/eap/gradle.mustache @@ -19,11 +19,11 @@ dependencies { providedCompile 'javax.validation:validation-api:1.1.0.Final' {{/useBeanValidation}} {{^java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.10.1' compile 'joda-time:joda-time:2.7' {{/java8}} {{#java8}} - compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.10' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1' {{/java8}} testCompile 'junit:junit:4.12', 'org.hamcrest:hamcrest-core:1.3' diff --git a/src/main/resources/mustache/JavaJaxRS/resteasy/eap/pom.mustache b/src/main/resources/mustache/JavaJaxRS/resteasy/eap/pom.mustache index 44d5452eb0..79caaf9363 100644 --- a/src/main/resources/mustache/JavaJaxRS/resteasy/eap/pom.mustache +++ b/src/main/resources/mustache/JavaJaxRS/resteasy/eap/pom.mustache @@ -187,30 +187,30 @@ com.fasterxml.jackson.datatype jackson-datatype-joda - 2.9.10 + 2.10.1 {{/java8}} {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.9.10 + 2.10.1 {{/java8}} com.fasterxml.jackson.core jackson-databind - 2.9.10 + 2.10.1 com.fasterxml.jackson.core jackson-core - 2.9.10 + 2.10.1 com.fasterxml.jackson.core jackson-annotations - 2.9.10 + 2.10.1 org.apache.httpcomponents @@ -230,7 +230,7 @@ 1.5.18 - 9.2.9.v20150224 + 9.3.27.v20190418 3.0.11.Final 1.6.3 4.8.1 From 0ebf8382268d0bce910f92c6132c45739edb30a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nat=C3=A1lia=20Oliveira?= Date: Wed, 30 Oct 2019 18:59:20 +0100 Subject: [PATCH 02/17] Add Cookie parameter to Spring code generation --- .../io/swagger/codegen/v3/generators/DefaultCodegenConfig.java | 2 +- src/main/resources/handlebars/JavaSpring/api.mustache | 3 ++- src/main/resources/handlebars/JavaSpring/cookieParams.mustache | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/handlebars/JavaSpring/cookieParams.mustache diff --git a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java index 62696a54dc..291352dac3 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java +++ b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java @@ -2223,7 +2223,7 @@ public int compare(CodegenParameter one, CodegenParameter another) { codegenOperation.pathParams = addHasMore(pathParams); codegenOperation.queryParams = addHasMore(queryParams); codegenOperation.headerParams = addHasMore(headerParams); - // op.cookieParams = cookieParams; + codegenOperation.cookieParams = addHasMore(cookieParams); codegenOperation.formParams = addHasMore(formParams); codegenOperation.requiredParams = addHasMore(requiredParams); codegenOperation.externalDocs = operation.getExternalDocs(); diff --git a/src/main/resources/handlebars/JavaSpring/api.mustache b/src/main/resources/handlebars/JavaSpring/api.mustache index 1880e3c60c..dc03180054 100644 --- a/src/main/resources/handlebars/JavaSpring/api.mustache +++ b/src/main/resources/handlebars/JavaSpring/api.mustache @@ -28,6 +28,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.bind.annotation.CookieValue; {{#jdk8-no-delegate}} import javax.servlet.http.HttpServletRequest; @@ -101,7 +102,7 @@ public interface {{classname}} { produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} method = RequestMethod.{{httpMethod}}) - {{#defaultInterfaces}}default {{/defaultInterfaces}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#parameters}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/parameters}}){{^defaultInterfaces}}{{#throwsException}} throws Exception{{/throwsException}};{{/defaultInterfaces}}{{#defaultInterfaces}}{{#throwsException}} throws Exception{{/throwsException}} { + {{#defaultInterfaces}}default {{/defaultInterfaces}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}({{#parameters}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>cookieParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/parameters}}){{^defaultInterfaces}}{{#throwsException}} throws Exception{{/throwsException}};{{/defaultInterfaces}}{{#defaultInterfaces}}{{#throwsException}} throws Exception{{/throwsException}} { {{#delegate-method}} return {{operationId}}({{#parameters}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/parameters}}); } diff --git a/src/main/resources/handlebars/JavaSpring/cookieParams.mustache b/src/main/resources/handlebars/JavaSpring/cookieParams.mustache new file mode 100644 index 0000000000..5edbd218e7 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/cookieParams.mustache @@ -0,0 +1 @@ +{{#isCookieParam}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^@last}}, {{/@last}}{{#@last}}{{/@last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @CookieValue(value="{{baseName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) {{>optionalDataType}} {{paramName}}{{/isCookieParam}} \ No newline at end of file From 382778af0bc61f7b352e219870cee0c758e0e3e9 Mon Sep 17 00:00:00 2001 From: frantuma Date: Sat, 16 Nov 2019 18:30:09 +0100 Subject: [PATCH 03/17] prepare release 1.0.14 --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index a587ac7c71..88c3f3954d 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ io.swagger.codegen.v3 swagger-codegen-generators - 1.0.14-SNAPSHOT + 1.0.14 jar @@ -246,9 +246,9 @@ - 3.0.14-SNAPSHOT - 2.0.16-SNAPSHOT - 2.0.11-SNAPSHOT + 3.0.14 + 2.0.16 + 2.1.0 2.10.1 2.11.1 3.3.0 From 248dbd4789db6d271be580240bcc0097372452f0 Mon Sep 17 00:00:00 2001 From: frantuma Date: Mon, 18 Nov 2019 12:35:08 +0100 Subject: [PATCH 04/17] bump next snapshot 1.0.15-SNAPSHOT --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 88c3f3954d..4452f76464 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ io.swagger.codegen.v3 swagger-codegen-generators - 1.0.14 + 1.0.15-SNAPSHOT jar @@ -247,8 +247,8 @@ 3.0.14 - 2.0.16 - 2.1.0 + 2.0.17-SNAPSHOT + 2.1.1-SNAPSHOT 2.10.1 2.11.1 3.3.0 From a552179ece88149d2223316a2ba7955bb11fbaed Mon Sep 17 00:00:00 2001 From: frantuma Date: Tue, 19 Nov 2019 15:46:42 +0100 Subject: [PATCH 05/17] bump codegen to 3.0.15-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4452f76464..bf3280346a 100644 --- a/pom.xml +++ b/pom.xml @@ -246,7 +246,7 @@ - 3.0.14 + 3.0.15-SNAPSHOT 2.0.17-SNAPSHOT 2.1.1-SNAPSHOT 2.10.1 From e2974a311a93a8b7b5c954817fa08c3bfee35418 Mon Sep 17 00:00:00 2001 From: HugoMario Date: Thu, 21 Nov 2019 11:10:49 -0500 Subject: [PATCH 06/17] set oneof/any composed schema alias in order to fix issue --- .../v3/generators/DefaultCodegenConfig.java | 2 ++ .../codegen/v3/generators/SchemaHandler.java | 3 +- .../AbstractTypeScriptClientCodegen.java | 7 +++-- .../typescript/TypeScriptSchemaHandler.java | 29 +++++++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/main/java/io/swagger/codegen/v3/generators/typescript/TypeScriptSchemaHandler.java diff --git a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java index 291352dac3..560864a033 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java +++ b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java @@ -1387,9 +1387,11 @@ else if (schema instanceof ComposedSchema) { } } if (oneOf != null && !oneOf.isEmpty()) { + codegenModel.dataType = getSchemaType(composed); this.schemaHandler.configureOneOfModel(codegenModel, oneOf); } if (anyOf != null && !anyOf.isEmpty()) { + codegenModel.dataType = getSchemaType(composed); this.schemaHandler.configureAnyOfModel(codegenModel, anyOf); } if (parent != null) { diff --git a/src/main/java/io/swagger/codegen/v3/generators/SchemaHandler.java b/src/main/java/io/swagger/codegen/v3/generators/SchemaHandler.java index ebd15d4887..5f456a15e6 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/SchemaHandler.java +++ b/src/main/java/io/swagger/codegen/v3/generators/SchemaHandler.java @@ -6,7 +6,6 @@ import io.swagger.codegen.v3.CodegenProperty; import io.swagger.codegen.v3.generators.util.OpenAPIUtil; import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.ObjectSchema; import io.swagger.v3.oas.models.media.Schema; import org.apache.commons.lang3.StringUtils; @@ -15,7 +14,7 @@ public class SchemaHandler { - private DefaultCodegenConfig codegenConfig; + protected DefaultCodegenConfig codegenConfig; public SchemaHandler(DefaultCodegenConfig codegenConfig) { this.codegenConfig = codegenConfig; diff --git a/src/main/java/io/swagger/codegen/v3/generators/typescript/AbstractTypeScriptClientCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/typescript/AbstractTypeScriptClientCodegen.java index f33b9fad0b..eae26c30b9 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/typescript/AbstractTypeScriptClientCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/typescript/AbstractTypeScriptClientCodegen.java @@ -114,6 +114,7 @@ public AbstractTypeScriptClientCodegen() { cliOptions.add(new CliOption(CodegenConstants.MODEL_PROPERTY_NAMING, CodegenConstants.MODEL_PROPERTY_NAMING_DESC).defaultValue("camelCase")); cliOptions.add(new CliOption(CodegenConstants.SUPPORTS_ES6, CodegenConstants.SUPPORTS_ES6_DESC).defaultValue("false")); + schemaHandler = new TypeScriptSchemaHandler(this); } @Override @@ -242,7 +243,7 @@ public String getTypeDeclaration(Schema propertySchema) { } @Override - protected void addImport(CodegenModel codegenModel, String type) { + public void addImport(CodegenModel codegenModel, String type) { if (type == null) { return; } @@ -286,9 +287,9 @@ public String toDefaultValue(Schema propertySchema) { } @Override - public String getSchemaType(Schema schema) { + public String getSchemaType(Schema schema) { String swaggerType = super.getSchemaType(schema); - if (swaggerType == null && schema instanceof ComposedSchema) { + if (schema instanceof ComposedSchema) { ComposedSchema composedSchema = (ComposedSchema)schema; if (composedSchema.getAllOf() != null && !composedSchema.getAllOf().isEmpty()) { return String.join(" & ", getTypesFromInterfaces(composedSchema.getAllOf())); diff --git a/src/main/java/io/swagger/codegen/v3/generators/typescript/TypeScriptSchemaHandler.java b/src/main/java/io/swagger/codegen/v3/generators/typescript/TypeScriptSchemaHandler.java new file mode 100644 index 0000000000..30db946b90 --- /dev/null +++ b/src/main/java/io/swagger/codegen/v3/generators/typescript/TypeScriptSchemaHandler.java @@ -0,0 +1,29 @@ +package io.swagger.codegen.v3.generators.typescript; + +import io.swagger.codegen.v3.CodegenConstants; +import io.swagger.codegen.v3.CodegenModel; +import io.swagger.codegen.v3.generators.DefaultCodegenConfig; +import io.swagger.codegen.v3.generators.SchemaHandler; +import io.swagger.v3.oas.models.media.Schema; + +import java.util.List; + +public class TypeScriptSchemaHandler extends SchemaHandler { + + private AbstractTypeScriptClientCodegen codegenConfig; + + public TypeScriptSchemaHandler(DefaultCodegenConfig codegenConfig) { + super(codegenConfig); + this.codegenConfig = (AbstractTypeScriptClientCodegen) codegenConfig; + } + + public void configureOneOfModel(CodegenModel codegenModel, List oneOf) { + codegenModel.getVendorExtensions().put(CodegenConstants.IS_ALIAS_EXT_NAME, Boolean.TRUE); + this.codegenConfig.addImport(codegenModel, codegenModel.dataType); + } + + public void configureAnyOfModel(CodegenModel codegenModel, List anyOf) { + codegenModel.getVendorExtensions().put(CodegenConstants.IS_ALIAS_EXT_NAME, Boolean.TRUE); + this.codegenConfig.addImport(codegenModel, codegenModel.dataType); + } +} From 8ca2a8721724c0f529974efb47fea94508f33059 Mon Sep 17 00:00:00 2001 From: HugoMario Date: Fri, 22 Nov 2019 08:06:11 -0500 Subject: [PATCH 07/17] updated templates to use cookie parameters. --- src/main/resources/handlebars/JavaJaxRS/api.mustache | 3 ++- src/main/resources/handlebars/JavaJaxRS/apiService.mustache | 2 +- .../resources/handlebars/JavaJaxRS/apiServiceImpl.mustache | 2 +- src/main/resources/handlebars/JavaJaxRS/bodyParams.mustache | 2 +- src/main/resources/handlebars/JavaJaxRS/cookieParams.mustache | 4 ++++ src/main/resources/handlebars/JavaJaxRS/headerParams.mustache | 2 +- src/main/resources/handlebars/JavaJaxRS/pathParams.mustache | 2 +- src/main/resources/handlebars/JavaJaxRS/queryParams.mustache | 2 +- .../handlebars/JavaJaxRS/serviceCookieParams.mustache | 1 + .../resources/mustache/JavaJaxRS/serviceCookieParams.mustache | 1 + 10 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/handlebars/JavaJaxRS/cookieParams.mustache create mode 100644 src/main/resources/handlebars/JavaJaxRS/serviceCookieParams.mustache create mode 100644 src/main/resources/mustache/JavaJaxRS/serviceCookieParams.mustache diff --git a/src/main/resources/handlebars/JavaJaxRS/api.mustache b/src/main/resources/handlebars/JavaJaxRS/api.mustache index 39489320ec..47295841f0 100644 --- a/src/main/resources/handlebars/JavaJaxRS/api.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/api.mustache @@ -11,6 +11,7 @@ import io.swagger.jaxrs.*; {{^useOas2}} import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -103,7 +104,7 @@ public class {{classname}} { @ApiResponse(responseCode = "{{{code}}}", description = "{{{message}}}"{{^vendorExtensions.x-java-is-response-void}}, content = @Content({{^containerType}}schema = @Schema(implementation = {{{baseType}}}.class)){{/containerType}}{{#containerType}}array = @ArraySchema(schema = @Schema(implementation = {{{baseType}}}.class))){{/containerType}}{{/vendorExtensions.x-java-is-response-void}}){{#hasMore}}, {{/hasMore}}{{/responses}} }) {{/useOas2}} - public Response {{nickname}}({{#parameters}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/parameters}}@Context SecurityContext securityContext) + public Response {{nickname}}({{#parameters}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}},{{/parameters}}@Context SecurityContext securityContext) throws NotFoundException { return delegate.{{nickname}}({{#parameters}}{{#isFile}}{{paramName}}InputStream, {{paramName}}Detail{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}},{{/parameters}}securityContext); } diff --git a/src/main/resources/handlebars/JavaJaxRS/apiService.mustache b/src/main/resources/handlebars/JavaJaxRS/apiService.mustache index 860dda7270..5bdc33e068 100644 --- a/src/main/resources/handlebars/JavaJaxRS/apiService.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/apiService.mustache @@ -24,7 +24,7 @@ import javax.validation.constraints.*; public abstract class {{classname}}Service { {{#operation}} {{#contents}} - public abstract Response {{nickname}}({{#parameters}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}},{{/parameters}}SecurityContext securityContext) throws NotFoundException; + public abstract Response {{nickname}}({{#parameters}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{>serviceCookieParams}},{{/parameters}}SecurityContext securityContext) throws NotFoundException; {{/contents}} {{/operation}} } diff --git a/src/main/resources/handlebars/JavaJaxRS/apiServiceImpl.mustache b/src/main/resources/handlebars/JavaJaxRS/apiServiceImpl.mustache index f43cc2774a..7c9bc7c412 100644 --- a/src/main/resources/handlebars/JavaJaxRS/apiServiceImpl.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/apiServiceImpl.mustache @@ -25,7 +25,7 @@ public class {{classname}}ServiceImpl extends {{classname}}Service { {{#operation}} {{#contents}} @Override - public Response {{nickname}}({{#parameters}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}, {{/parameters}}SecurityContext securityContext) throws NotFoundException { + public Response {{nickname}}({{#parameters}}{{>serviceQueryParams}}{{>servicePathParams}}{{>serviceHeaderParams}}{{>serviceBodyParams}}{{>serviceFormParams}}{{>serviceCookieParams}}, {{/parameters}}SecurityContext securityContext) throws NotFoundException { // do some magic! return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build(); } diff --git a/src/main/resources/handlebars/JavaJaxRS/bodyParams.mustache b/src/main/resources/handlebars/JavaJaxRS/bodyParams.mustache index e590766510..c59102015c 100644 --- a/src/main/resources/handlebars/JavaJaxRS/bodyParams.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/bodyParams.mustache @@ -3,6 +3,6 @@ @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}} {{/useOas2}} {{^useOas2}} -@Parameter(description = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}} +@Parameter(ParameterIn.DEFAULT, description = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}} {{/useOas2}} {{/is}} \ No newline at end of file diff --git a/src/main/resources/handlebars/JavaJaxRS/cookieParams.mustache b/src/main/resources/handlebars/JavaJaxRS/cookieParams.mustache new file mode 100644 index 0000000000..773f7661ea --- /dev/null +++ b/src/main/resources/handlebars/JavaJaxRS/cookieParams.mustache @@ -0,0 +1,4 @@ +{{#isCookieParam}} +{{#useOas2}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{/useOas2}} +{{^useOas2}}@Parameter(in = ParameterIn.COOKIE, description = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) {{{dataType}}} {{paramName}}{{/useOas2}} +{{/isCookieParam}} diff --git a/src/main/resources/handlebars/JavaJaxRS/headerParams.mustache b/src/main/resources/handlebars/JavaJaxRS/headerParams.mustache index 03d9996941..7844338a2e 100644 --- a/src/main/resources/handlebars/JavaJaxRS/headerParams.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/headerParams.mustache @@ -1,4 +1,4 @@ {{#is this 'header-param'}} {{#useOas2}}@ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}})@HeaderParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}} -{{^useOas2}}@Parameter(description = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}})@HeaderParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}} +{{^useOas2}}@Parameter(ParameterIn.HEADER, description = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}})@HeaderParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}} {{/is}} \ No newline at end of file diff --git a/src/main/resources/handlebars/JavaJaxRS/pathParams.mustache b/src/main/resources/handlebars/JavaJaxRS/pathParams.mustache index b0a7d6fdde..2340b6c86d 100644 --- a/src/main/resources/handlebars/JavaJaxRS/pathParams.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/pathParams.mustache @@ -1 +1 @@ -{{~#is this 'path-param'}}{{#useOas2}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{^useOas2}}@Parameter(description = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{/is}} \ No newline at end of file +{{~#is this 'path-param'}}{{#useOas2}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{^useOas2}}@Parameter(ParameterIn.PATH, description = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @PathParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{/is}} \ No newline at end of file diff --git a/src/main/resources/handlebars/JavaJaxRS/queryParams.mustache b/src/main/resources/handlebars/JavaJaxRS/queryParams.mustache index c5bf2d4b84..d43d80b993 100644 --- a/src/main/resources/handlebars/JavaJaxRS/queryParams.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/queryParams.mustache @@ -1 +1 @@ -{{#is this 'query-param'}}{{#useOas2}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{#defaultValue}} @DefaultValue("{{{defaultValue}}}"){{/defaultValue}} @QueryParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{^useOas2}}@Parameter(description = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{#defaultValue}} @DefaultValue("{{{defaultValue}}}"){{/defaultValue}} @QueryParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{/is}} \ No newline at end of file +{{#is this 'query-param'}}{{#useOas2}}@ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{#defaultValue}} @DefaultValue("{{{defaultValue}}}"){{/defaultValue}} @QueryParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{^useOas2}}@Parameter(ParameterIn.QUERY, description = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{#defaultValue}} @DefaultValue("{{{defaultValue}}}"){{/defaultValue}} @QueryParam("{{baseName}}") {{{dataType}}} {{paramName}}{{/useOas2}}{{/is}} \ No newline at end of file diff --git a/src/main/resources/handlebars/JavaJaxRS/serviceCookieParams.mustache b/src/main/resources/handlebars/JavaJaxRS/serviceCookieParams.mustache new file mode 100644 index 0000000000..70871f0f8c --- /dev/null +++ b/src/main/resources/handlebars/JavaJaxRS/serviceCookieParams.mustache @@ -0,0 +1 @@ +{{#isCookieParam}}{{{dataType}}} {{paramName}}{{/isCookieParam}} \ No newline at end of file diff --git a/src/main/resources/mustache/JavaJaxRS/serviceCookieParams.mustache b/src/main/resources/mustache/JavaJaxRS/serviceCookieParams.mustache new file mode 100644 index 0000000000..70871f0f8c --- /dev/null +++ b/src/main/resources/mustache/JavaJaxRS/serviceCookieParams.mustache @@ -0,0 +1 @@ +{{#isCookieParam}}{{{dataType}}} {{paramName}}{{/isCookieParam}} \ No newline at end of file From ae01fe8d2478ab87a4573225fa7d851763350110 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 28 Nov 2019 17:29:14 +0100 Subject: [PATCH 08/17] fix openapi-yaml - don't create json file --- .../codegen/v3/generators/openapi/OpenAPIYamlGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/swagger/codegen/v3/generators/openapi/OpenAPIYamlGenerator.java b/src/main/java/io/swagger/codegen/v3/generators/openapi/OpenAPIYamlGenerator.java index 4b4ac7ed6a..2287a8c7ae 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/openapi/OpenAPIYamlGenerator.java +++ b/src/main/java/io/swagger/codegen/v3/generators/openapi/OpenAPIYamlGenerator.java @@ -36,7 +36,7 @@ public void setOutputFile(String outputFile) { @Override public void preprocessOpenAPI(OpenAPI openAPI) { - super.preprocessOpenAPI(openAPI); + this.openAPI = openAPI; try { final String outputString; if (flattenSpec) { From 23b12c34c98c806d9ebcba43bdbc666a721a189b Mon Sep 17 00:00:00 2001 From: frantuma Date: Fri, 29 Nov 2019 11:29:27 +0100 Subject: [PATCH 09/17] fix jaxrs-jersey missing openApi causing ref properties attributed to be missing --- .../v3/generators/java/AbstractJavaJAXRSServerCodegen.java | 1 + src/main/resources/handlebars/JavaJaxRS/api.mustache | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/swagger/codegen/v3/generators/java/AbstractJavaJAXRSServerCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/java/AbstractJavaJAXRSServerCodegen.java index dc2fe3cfd4..a78bf17935 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/java/AbstractJavaJAXRSServerCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/java/AbstractJavaJAXRSServerCodegen.java @@ -92,6 +92,7 @@ public void processOpts() { @Override public void preprocessOpenAPI(OpenAPI openAPI) { //this.openAPIUtil = new OpenAPIUtil(openAPI); + this.openAPI = openAPI; if (!this.additionalProperties.containsKey("serverPort")) { final URL urlInfo = URLPathUtil.getServerURL(openAPI); String port = "8080"; // Default value for a JEE Server diff --git a/src/main/resources/handlebars/JavaJaxRS/api.mustache b/src/main/resources/handlebars/JavaJaxRS/api.mustache index 47295841f0..66548c9082 100644 --- a/src/main/resources/handlebars/JavaJaxRS/api.mustache +++ b/src/main/resources/handlebars/JavaJaxRS/api.mustache @@ -11,7 +11,7 @@ import io.swagger.jaxrs.*; {{^useOas2}} import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn +import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.media.ArraySchema; From 6aae1e1e1852b419f73124215a491702e1006385 Mon Sep 17 00:00:00 2001 From: HugoMario Date: Fri, 6 Dec 2019 13:34:57 -0500 Subject: [PATCH 10/17] added generator class --- .../v3/generators/swift/Swift5Codegen.java | 837 ++++++++++++++++++ 1 file changed, 837 insertions(+) create mode 100644 src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java diff --git a/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java b/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java new file mode 100644 index 0000000000..182e5a116f --- /dev/null +++ b/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java @@ -0,0 +1,837 @@ +package io.swagger.codegen.v3.generators.swift; + + + +import io.swagger.codegen.v3.CliOption; +import io.swagger.codegen.v3.CodegenConstants; +import io.swagger.codegen.v3.CodegenModel; +import io.swagger.codegen.v3.CodegenOperation; +import io.swagger.codegen.v3.CodegenProperty; +import io.swagger.codegen.v3.CodegenType; +import io.swagger.codegen.v3.SupportingFile; +import io.swagger.codegen.v3.generators.DefaultCodegenConfig; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.Schema; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static io.swagger.codegen.v3.generators.handlebars.ExtensionHelper.getBooleanValue; + +public class Swift5Codegen extends DefaultCodegenConfig { + protected static final Logger LOGGER = LoggerFactory.getLogger(Swift5Codegen.class); + + public static final String PROJECT_NAME = "projectName"; + public static final String RESPONSE_AS = "responseAs"; + public static final String UNWRAP_REQUIRED = "unwrapRequired"; + public static final String OBJC_COMPATIBLE = "objcCompatible"; + public static final String POD_SOURCE = "podSource"; + public static final String POD_AUTHORS = "podAuthors"; + public static final String POD_SOCIAL_MEDIA_URL = "podSocialMediaURL"; + public static final String POD_DOCSET_URL = "podDocsetURL"; + public static final String POD_LICENSE = "podLicense"; + public static final String POD_HOMEPAGE = "podHomepage"; + public static final String POD_SUMMARY = "podSummary"; + public static final String POD_DESCRIPTION = "podDescription"; + public static final String POD_SCREENSHOTS = "podScreenshots"; + public static final String POD_DOCUMENTATION_URL = "podDocumentationURL"; + public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace"; + public static final String DEFAULT_POD_AUTHORS = "Swagger Codegen"; + public static final String LENIENT_TYPE_CAST = "lenientTypeCast"; + private static final String LIBRARY_PROMISE_KIT = "PromiseKit"; + private static final String LIBRARY_RX_SWIFT = "RxSwift"; + private static final String[] RESPONSE_LIBRARIES = {LIBRARY_PROMISE_KIT, LIBRARY_RX_SWIFT}; + protected String projectName = "SwaggerClient"; + private boolean unwrapRequired; + private boolean objcCompatible = false; + private boolean lenientTypeCast = false; + protected boolean swiftUseApiNamespace; + private String[] responseAs = new String[0]; + protected String sourceFolder = "Classes" + File.separator + "Swaggers"; + + @Override + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + @Override + public String getName() { + return "swift5"; + } + + @Override + public String getHelp() { + return "Generates a swift client library."; + } + + @Override + protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, + Schema swaggerModel) { + + final Object additionalProperties = swaggerModel.getAdditionalProperties(); + + if (additionalProperties != null && additionalProperties instanceof Schema) { + codegenModel.additionalPropertiesType = getSchemaType((Schema) additionalProperties); + } + } + + /** + * Constructor for the swift5 language codegen module. + */ + public Swift5Codegen() { + super(); + outputFolder = "generated-code" + File.separator + "swift"; + modelTemplateFiles.put("model.mustache", ".swift"); + apiTemplateFiles.put("api.mustache", ".swift"); + embeddedTemplateDir = templateDir = "swift5"; + apiPackage = File.separator + "APIs"; + modelPackage = File.separator + "Models"; + + languageSpecificPrimitives = new HashSet<>( + Arrays.asList( + "Int", + "Int32", + "Int64", + "Float", + "Double", + "Bool", + "Void", + "String", + "Character", + "AnyObject", + "Any") + ); + defaultIncludes = new HashSet<>( + Arrays.asList( + "Data", + "Date", + "URL", // for file + "UUID", + "Array", + "Dictionary", + "Set", + "Any", + "Empty", + "AnyObject", + "Any") + ); + reservedWords = new HashSet<>( + Arrays.asList( + // name used by swift client + "ErrorResponse", "Response", + + // Added for Objective-C compatibility + "id", "description", "NSArray", "NSURL", "CGFloat", "NSSet", "NSString", "NSInteger", "NSUInteger", + "NSError", "NSDictionary", + + // + // Swift keywords. This list is taken from here: + // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410 + // + // Keywords used in declarations + "associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func", "import", "init", + "inout", "internal", "let", "open", "operator", "private", "protocol", "public", "static", "struct", + "subscript", "typealias", "var", + // Keywords uses in statements + "break", "case", "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if", + "in", "repeat", "return", "switch", "where", "while", + // Keywords used in expressions and types + "as", "Any", "catch", "false", "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws", "true", "try", + // Keywords used in patterns + "_", + // Keywords that begin with a number sign + "#available", "#colorLiteral", "#column", "#else", "#elseif", "#endif", "#file", "#fileLiteral", "#function", "#if", + "#imageLiteral", "#line", "#selector", "#sourceLocation", + // Keywords reserved in particular contexts + "associativity", "convenience", "dynamic", "didSet", "final", "get", "infix", "indirect", "lazy", "left", + "mutating", "none", "nonmutating", "optional", "override", "postfix", "precedence", "prefix", "Protocol", + "required", "right", "set", "Type", "unowned", "weak", "willSet", + + // + // Swift Standard Library types + // https://developer.apple.com/documentation/swift + // + // Numbers and Basic Values + "Bool", "Int", "Double", "Float", "Range", "ClosedRange", "Error", "Optional", + // Special-Use Numeric Types + "UInt", "UInt8", "UInt16", "UInt32", "UInt64", "Int8", "Int16", "Int32", "Int64", "Float80", "Float32", "Float64", + // Strings and Text + "String", "Character", "Unicode", "StaticString", + // Collections + "Array", "Dictionary", "Set", "OptionSet", "CountableRange", "CountableClosedRange", + + // The following are commonly-used Foundation types + "URL", "Data", "Codable", "Encodable", "Decodable", + + // The following are other words we want to reserve + "Void", "AnyObject", "Class", "dynamicType", "COLUMN", "FILE", "FUNCTION", "LINE" + ) + ); + + typeMapping = new HashMap<>(); + typeMapping.put("array", "Array"); + typeMapping.put("List", "Array"); + typeMapping.put("map", "Dictionary"); + typeMapping.put("date", "Date"); + typeMapping.put("Date", "Date"); + typeMapping.put("DateTime", "Date"); + typeMapping.put("boolean", "Bool"); + typeMapping.put("string", "String"); + typeMapping.put("char", "Character"); + typeMapping.put("short", "Int"); + typeMapping.put("int", "Int"); + typeMapping.put("long", "Int64"); + typeMapping.put("integer", "Int"); + typeMapping.put("Integer", "Int"); + typeMapping.put("float", "Float"); + typeMapping.put("number", "Double"); + typeMapping.put("double", "Double"); + typeMapping.put("object", "JSONValue"); + typeMapping.put("file", "URL"); + typeMapping.put("binary", "Data"); + typeMapping.put("ByteArray", "Data"); + typeMapping.put("UUID", "UUID"); + + importMapping = new HashMap<>(); + + cliOptions.add(new CliOption(PROJECT_NAME, "Project name in Xcode")); + cliOptions.add(new CliOption(RESPONSE_AS, + "Optionally use libraries to manage response. Currently " + + StringUtils.join(RESPONSE_LIBRARIES, ", ") + + " are available.")); + cliOptions.add(new CliOption(UNWRAP_REQUIRED, + "Treat 'required' properties in response as non-optional " + + "(which would crash the app if api returns null as opposed " + + "to required option specified in json schema")); + cliOptions.add(new CliOption(OBJC_COMPATIBLE, + "Add additional properties and methods for Objective-C " + + "compatibility (default: false)")); + cliOptions.add(new CliOption(POD_SOURCE, "Source information used for Podspec")); + cliOptions.add(new CliOption(CodegenConstants.POD_VERSION, "Version used for Podspec")); + cliOptions.add(new CliOption(POD_AUTHORS, "Authors used for Podspec")); + cliOptions.add(new CliOption(POD_SOCIAL_MEDIA_URL, "Social Media URL used for Podspec")); + cliOptions.add(new CliOption(POD_DOCSET_URL, "Docset URL used for Podspec")); + cliOptions.add(new CliOption(POD_LICENSE, "License used for Podspec")); + cliOptions.add(new CliOption(POD_HOMEPAGE, "Homepage used for Podspec")); + cliOptions.add(new CliOption(POD_SUMMARY, "Summary used for Podspec")); + cliOptions.add(new CliOption(POD_DESCRIPTION, "Description used for Podspec")); + cliOptions.add(new CliOption(POD_SCREENSHOTS, "Screenshots used for Podspec")); + cliOptions.add(new CliOption(POD_DOCUMENTATION_URL, + "Documentation URL used for Podspec")); + cliOptions.add(new CliOption(SWIFT_USE_API_NAMESPACE, + "Flag to make all the API classes inner-class " + + "of {{projectName}}API")); + cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, + CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC) + .defaultValue(Boolean.TRUE.toString())); + cliOptions.add(new CliOption(LENIENT_TYPE_CAST, + "Accept and cast values for simple types (string->bool, " + + "string->int, int->string)") + .defaultValue(Boolean.FALSE.toString())); + } + + @Override + public void processOpts() { + super.processOpts(); + + // Setup project name + if (additionalProperties.containsKey(PROJECT_NAME)) { + setProjectName((String) additionalProperties.get(PROJECT_NAME)); + } else { + additionalProperties.put(PROJECT_NAME, projectName); + } + sourceFolder = projectName + File.separator + sourceFolder; + + // Setup unwrapRequired option, which makes all the + // properties with "required" non-optional + if (additionalProperties.containsKey(UNWRAP_REQUIRED)) { + setUnwrapRequired(convertPropertyToBooleanAndWriteBack(UNWRAP_REQUIRED)); + } + additionalProperties.put(UNWRAP_REQUIRED, unwrapRequired); + + // Setup objcCompatible option, which adds additional properties + // and methods for Objective-C compatibility + if (additionalProperties.containsKey(OBJC_COMPATIBLE)) { + setObjcCompatible(convertPropertyToBooleanAndWriteBack(OBJC_COMPATIBLE)); + } + additionalProperties.put(OBJC_COMPATIBLE, objcCompatible); + + // Setup unwrapRequired option, which makes all the properties with "required" non-optional + if (additionalProperties.containsKey(RESPONSE_AS)) { + Object responseAsObject = additionalProperties.get(RESPONSE_AS); + if (responseAsObject instanceof String) { + setResponseAs(((String) responseAsObject).split(",")); + } else { + setResponseAs((String[]) responseAsObject); + } + } + additionalProperties.put(RESPONSE_AS, responseAs); + if (ArrayUtils.contains(responseAs, LIBRARY_PROMISE_KIT)) { + additionalProperties.put("usePromiseKit", true); + } + if (ArrayUtils.contains(responseAs, LIBRARY_RX_SWIFT)) { + additionalProperties.put("useRxSwift", true); + } + + // Setup swiftUseApiNamespace option, which makes all the API + // classes inner-class of {{projectName}}API + if (additionalProperties.containsKey(SWIFT_USE_API_NAMESPACE)) { + setSwiftUseApiNamespace(convertPropertyToBooleanAndWriteBack(SWIFT_USE_API_NAMESPACE)); + } + + if (!additionalProperties.containsKey(POD_AUTHORS)) { + additionalProperties.put(POD_AUTHORS, DEFAULT_POD_AUTHORS); + } + + setLenientTypeCast(convertPropertyToBooleanAndWriteBack(LENIENT_TYPE_CAST)); + + supportingFiles.add(new SupportingFile("Podspec.mustache", + "", + projectName + ".podspec")); + supportingFiles.add(new SupportingFile("Cartfile.mustache", + "", + "Cartfile")); + supportingFiles.add(new SupportingFile("APIHelper.mustache", + sourceFolder, + "APIHelper.swift")); + supportingFiles.add(new SupportingFile("AlamofireImplementations.mustache", + sourceFolder, + "AlamofireImplementations.swift")); + supportingFiles.add(new SupportingFile("Configuration.mustache", + sourceFolder, + "Configuration.swift")); + supportingFiles.add(new SupportingFile("Extensions.mustache", + sourceFolder, + "Extensions.swift")); + supportingFiles.add(new SupportingFile("Models.mustache", + sourceFolder, + "Models.swift")); + supportingFiles.add(new SupportingFile("APIs.mustache", + sourceFolder, + "APIs.swift")); + supportingFiles.add(new SupportingFile("CodableHelper.mustache", + sourceFolder, + "CodableHelper.swift")); + supportingFiles.add(new SupportingFile("JSONEncodableEncoding.mustache", + sourceFolder, + "JSONEncodableEncoding.swift")); + supportingFiles.add(new SupportingFile("JSONEncodingHelper.mustache", + sourceFolder, + "JSONEncodingHelper.swift")); + supportingFiles.add(new SupportingFile("JSONValue.mustache", + sourceFolder, + "JSONValue.swift")); + supportingFiles.add(new SupportingFile("git_push.sh.mustache", + "", + "git_push.sh")); + supportingFiles.add(new SupportingFile("gitignore.mustache", + "", + ".gitignore")); + + } + + @Override + protected boolean isReservedWord(String word) { + return word != null && reservedWords.contains(word); //don't lowercase as super does + } + + @Override + public String getDefaultTemplateDir() { + return "swift5"; + } + + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; // add an underscore to the name + } + + @Override + public String modelFileFolder() { + return outputFolder + File.separator + sourceFolder + + modelPackage().replace('.', File.separatorChar); + } + + @Override + public String apiFileFolder() { + return outputFolder + File.separator + sourceFolder + + apiPackage().replace('.', File.separatorChar); + } + + @Override + public String getTypeDeclaration(Schema prop) { + if (prop instanceof ArraySchema) { + ArraySchema arraySchema = (ArraySchema) prop; + Schema inner = arraySchema.getItems(); + return "[" + getTypeDeclaration(inner) + "]"; + } else if (prop instanceof MapSchema) { + MapSchema mp = (MapSchema) prop; + Object inner = mp.getAdditionalProperties(); + if (inner instanceof Schema) { + return "[String:" + getTypeDeclaration((Schema) inner) + "]"; + } + } + return super.getTypeDeclaration(prop); + } + + @Override + public String getSchemaType(Schema prop) { + String schemaType = super.getSchemaType(prop); + String type; + if (typeMapping.containsKey(schemaType)) { + type = typeMapping.get(schemaType); + if (languageSpecificPrimitives.contains(type) || defaultIncludes.contains(type)) { + return type; + } + } else { + type = schemaType; + } + return toModelName(type); + } + + @Override + public boolean isDataTypeFile(String dataType) { + return dataType != null && dataType.equals("URL"); + } + + @Override + public boolean isDataTypeBinary(final String dataType) { + return dataType != null && dataType.equals("Data"); + } + + /** + * Output the proper model name (capitalized). + * + * @param name the name of the model + * @return capitalized model name + */ + @Override + public String toModelName(String name) { + // FIXME parameter should not be assigned. Also declare it as "final" + name = sanitizeName(name); + + if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix + name = name + "_" + modelNameSuffix; + } + + if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix + name = modelNamePrefix + "_" + name; + } + + // camelize the model name + // phone_number => PhoneNumber + name = camelize(name); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(name)) { + String modelName = "Model" + name; + LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + + modelName); + return modelName; + } + + // model name starts with number + if (name.matches("^\\d.*")) { + // e.g. 200Response => Model200Response (after camelize) + String modelName = "Model" + name; + LOGGER.warn(name + + " (model name starts with number) cannot be used as model name." + + " Renamed to " + modelName); + return modelName; + } + + return name; + } + + /** + * Return the capitalized file name of the model. + * + * @param name the model name + * @return the file name of the model + */ + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String toDefaultValue(Schema prop) { + // nil + return null; + } + + @Override + public String toInstantiationType(Schema prop) { + if (prop instanceof MapSchema) { + MapSchema mapSchema = (MapSchema) prop; + if (mapSchema.getAdditionalProperties() != null && mapSchema.getAdditionalProperties() instanceof Schema) { + return getSchemaType((Schema) mapSchema.getAdditionalProperties()); + } + } else if (prop instanceof ArraySchema) { + ArraySchema ap = (ArraySchema) prop; + String inner = getSchemaType(ap.getItems()); + return "[" + inner + "]"; + } + return null; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultAPI"; + } + return initialCaps(name) + "API"; + } + + @Override + public String toOperationId(String operationId) { + operationId = camelize(sanitizeName(operationId), true); + + // Throw exception if method name is empty. + // This should not happen but keep the check just in case + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method name (operationId) not allowed"); + } + + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + String newOperationId = camelize(("call_" + operationId), true); + LOGGER.warn(operationId + " (reserved word) cannot be used as method name." + + " Renamed to " + newOperationId); + return newOperationId; + } + + return operationId; + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + // camelize the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // sanitize name + name = sanitizeName(name); + + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) { + return name; + } + + // camelize(lower) the variable name + // pet_id => petId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (isReservedWord(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public CodegenModel fromModel(String name, Schema model, Map allDefinitions) { + CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); + if (codegenModel.description != null) { + codegenModel.imports.add("ApiModel"); + } + if (allDefinitions != null) { + String parentSchema = codegenModel.parentSchema; + + // multilevel inheritance: reconcile properties of all the parents + while (parentSchema != null) { + final Schema parentModel = allDefinitions.get(parentSchema); + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, + parentModel, + allDefinitions); + reconcileProperties(codegenModel, parentCodegenModel); + + // get the next parent + parentSchema = parentCodegenModel.parentSchema; + } + } + + return codegenModel; + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map definitions, OpenAPI openAPI) { + CodegenOperation codegenOperation = super.fromOperation(path, httpMethod, operation, definitions, openAPI); + + if (codegenOperation.returnType != null && codegenOperation.returnType.equals("Any")) { + codegenOperation.returnType = null; + } + + return codegenOperation; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public void setUnwrapRequired(boolean unwrapRequired) { + this.unwrapRequired = unwrapRequired; + } + + public void setObjcCompatible(boolean objcCompatible) { + this.objcCompatible = objcCompatible; + } + + public void setLenientTypeCast(boolean lenientTypeCast) { + this.lenientTypeCast = lenientTypeCast; + } + + public void setResponseAs(String[] responseAs) { + this.responseAs = responseAs; + } + + public void setSwiftUseApiNamespace(boolean swiftUseApiNamespace) { + this.swiftUseApiNamespace = swiftUseApiNamespace; + } + + @Override + public String toEnumValue(String value, String datatype) { + return String.valueOf(value); + } + + @Override + public String toEnumDefaultValue(String value, String datatype) { + return datatype + "_" + value; + } + + @Override + public String toEnumVarName(String name, String datatype) { + if (name.length() == 0) { + return "empty"; + } + + Pattern startWithNumberPattern = Pattern.compile("^\\d+"); + Matcher startWithNumberMatcher = startWithNumberPattern.matcher(name); + if (startWithNumberMatcher.find()) { + String startingNumbers = startWithNumberMatcher.group(0); + String nameWithoutStartingNumbers = name.substring(startingNumbers.length()); + + return "_" + startingNumbers + camelize(nameWithoutStartingNumbers, true); + } + + // for symbol, e.g. $, # + if (getSymbolName(name) != null) { + return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase()), true); + } + + // Camelize only when we have a structure defined below + boolean camelized = false; + if (name.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) { + name = camelize(name, true); + camelized = true; + } + + // Reserved Name + String nameLowercase = StringUtils.lowerCase(name); + if (isReservedWord(nameLowercase)) { + return escapeReservedWord(nameLowercase); + } + + // Check for numerical conversions + if ("Int".equals(datatype) || "Int32".equals(datatype) || "Int64".equals(datatype) + || "Float".equals(datatype) || "Double".equals(datatype)) { + String varName = "number" + camelize(name); + varName = varName.replaceAll("-", "minus"); + varName = varName.replaceAll("\\+", "plus"); + varName = varName.replaceAll("\\.", "dot"); + return varName; + } + + // If we have already camelized the word, don't progress + // any further + if (camelized) { + return name; + } + + char[] separators = {'-', '_', ' ', ':', '(', ')'}; + return camelize(WordUtils.capitalizeFully(StringUtils.lowerCase(name), separators) + .replaceAll("[-_ :()]", ""), + true); + } + + @Override + public String toEnumName(CodegenProperty property) { + String enumName = toModelName(property.name); + + // Ensure that the enum type doesn't match a reserved word or + // the variable name doesn't match the generated enum type or the + // Swift compiler will generate an error + if (isReservedWord(property.datatypeWithEnum) + || toVarName(property.name).equals(property.datatypeWithEnum)) { + enumName = property.datatypeWithEnum + "Enum"; + } + + // TODO: toModelName already does something for names starting with number, + // so this code is probably never called + if (enumName.matches("\\d.*")) { // starts with number + return "_" + enumName; + } else { + return enumName; + } + } + + @Override + public Map postProcessModels(Map objs) { + Map postProcessedModelsEnum = postProcessModelsEnum(objs); + + // We iterate through the list of models, and also iterate through each of the + // properties for each model. For each property, if: + // + // CodegenProperty.name != CodegenProperty.baseName + // + // then we set + // + // CodegenProperty.vendorExtensions["x-codegen-escaped-property-name"] = true + // + // Also, if any property in the model has x-codegen-escaped-property-name=true, then we mark: + // + // CodegenModel.vendorExtensions["x-codegen-has-escaped-property-names"] = true + // + List models = (List) postProcessedModelsEnum.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + boolean modelHasPropertyWithEscapedName = false; + for (CodegenProperty prop : cm.allVars) { + if (!prop.name.equals(prop.baseName)) { + prop.vendorExtensions.put("x-codegen-escaped-property-name", true); + modelHasPropertyWithEscapedName = true; + } + } + if (modelHasPropertyWithEscapedName) { + cm.vendorExtensions.put("x-codegen-has-escaped-property-names", true); + } + } + + return postProcessedModelsEnum; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + + // The default template code has the following logic for + // assigning a type as Swift Optional: + // + // {{^unwrapRequired}}?{{/unwrapRequired}} + // {{#unwrapRequired}}{{^required}}?{{/required}}{{/unwrapRequired}} + // + // which means: + // + // boolean isSwiftOptional = !unwrapRequired || (unwrapRequired && !property.required); + // + // We can drop the check for unwrapRequired in (unwrapRequired && !property.required) + // due to short-circuit evaluation of the || operator. + boolean isSwiftOptional = !unwrapRequired || !property.required; + boolean isSwiftScalarType = getBooleanValue(property, CodegenConstants.IS_INTEGER_EXT_NAME) + || getBooleanValue(property, CodegenConstants.IS_LONG_EXT_NAME) + || getBooleanValue(property, CodegenConstants.IS_FLOAT_EXT_NAME) + || getBooleanValue(property, CodegenConstants.IS_DOUBLE_EXT_NAME) + || getBooleanValue(property, CodegenConstants.IS_BOOLEAN_EXT_NAME); + + if (isSwiftOptional && isSwiftScalarType) { + // Optional scalar types like Int?, Int64?, Float?, Double?, and Bool? + // do not translate to Objective-C. So we want to flag those + // properties in case we want to put special code in the templates + // which provide Objective-C compatibility. + property.vendorExtensions.put("x-swift-optional-scalar", true); + } + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + private static void reconcileProperties(CodegenModel codegenModel, + CodegenModel parentCodegenModel) { + // To support inheritance in this generator, we will analyze + // the parent and child models, look for properties that match, and remove + // them from the child models and leave them in the parent. + // Because the child models extend the parents, the properties + // will be available via the parent. + + // Get the properties for the parent and child models + final List parentModelCodegenProperties = parentCodegenModel.vars; + List codegenProperties = codegenModel.vars; + codegenModel.allVars = new ArrayList<>(codegenProperties); + codegenModel.parentVars = parentCodegenModel.allVars; + + // Iterate over all of the parent model properties + boolean removedChildProperty = false; + + for (CodegenProperty parentModelCodegenProperty : parentModelCodegenProperties) { + // Now that we have found a prop in the parent class, + // and search the child class for the same prop. + Iterator iterator = codegenProperties.iterator(); + while (iterator.hasNext()) { + CodegenProperty codegenProperty = iterator.next(); + if (codegenProperty.baseName.equals(parentModelCodegenProperty.baseName)) { + // We found a property in the child class that is + // a duplicate of the one in the parent, so remove it. + iterator.remove(); + removedChildProperty = true; + } + } + } + + if (removedChildProperty) { + // If we removed an entry from this model's vars, we need to ensure hasMore is updated + int count = 0; + int numVars = codegenProperties.size(); + for (CodegenProperty codegenProperty : codegenProperties) { + count += 1; + codegenProperty.getVendorExtensions().put(CodegenConstants.HAS_MORE_EXT_NAME, count < numVars); + } + codegenModel.vars = codegenProperties; + } + } +} + From f5354b0415c968fc6d22ca0d54054c886c2047f7 Mon Sep 17 00:00:00 2001 From: HugoMario Date: Fri, 6 Dec 2019 13:35:15 -0500 Subject: [PATCH 11/17] added swift 5 templates --- .../handlebars/swift5/APIHelper.mustache | 65 +++ .../resources/handlebars/swift5/APIs.mustache | 61 +++ .../swift5/AlamofireImplementations.mustache | 422 ++++++++++++++++++ .../handlebars/swift5/Cartfile.mustache | 3 + .../handlebars/swift5/CodableHelper.mustache | 93 ++++ .../handlebars/swift5/Configuration.mustache | 15 + .../handlebars/swift5/Extensions.mustache | 186 ++++++++ .../swift5/JSONEncodableEncoding.mustache | 54 +++ .../swift5/JSONEncodingHelper.mustache | 43 ++ .../handlebars/swift5/JSONValue.mustache | 99 ++++ .../handlebars/swift5/Models.mustache | 36 ++ .../handlebars/swift5/Podspec.mustache | 22 + .../handlebars/swift5/README.mustache | 65 +++ .../handlebars/swift5/_param.mustache | 1 + .../resources/handlebars/swift5/api.mustache | 162 +++++++ .../handlebars/swift5/git_push.sh.mustache | 52 +++ .../handlebars/swift5/gitignore.mustache | 63 +++ .../handlebars/swift5/model.mustache | 25 ++ .../handlebars/swift5/modelArray.mustache | 1 + .../handlebars/swift5/modelEnum.mustache | 4 + .../modelInlineEnumDeclaration.mustache | 3 + .../handlebars/swift5/modelObject.mustache | 82 ++++ 22 files changed, 1557 insertions(+) create mode 100644 src/main/resources/handlebars/swift5/APIHelper.mustache create mode 100644 src/main/resources/handlebars/swift5/APIs.mustache create mode 100644 src/main/resources/handlebars/swift5/AlamofireImplementations.mustache create mode 100644 src/main/resources/handlebars/swift5/Cartfile.mustache create mode 100644 src/main/resources/handlebars/swift5/CodableHelper.mustache create mode 100644 src/main/resources/handlebars/swift5/Configuration.mustache create mode 100644 src/main/resources/handlebars/swift5/Extensions.mustache create mode 100644 src/main/resources/handlebars/swift5/JSONEncodableEncoding.mustache create mode 100644 src/main/resources/handlebars/swift5/JSONEncodingHelper.mustache create mode 100644 src/main/resources/handlebars/swift5/JSONValue.mustache create mode 100644 src/main/resources/handlebars/swift5/Models.mustache create mode 100644 src/main/resources/handlebars/swift5/Podspec.mustache create mode 100644 src/main/resources/handlebars/swift5/README.mustache create mode 100644 src/main/resources/handlebars/swift5/_param.mustache create mode 100644 src/main/resources/handlebars/swift5/api.mustache create mode 100755 src/main/resources/handlebars/swift5/git_push.sh.mustache create mode 100644 src/main/resources/handlebars/swift5/gitignore.mustache create mode 100644 src/main/resources/handlebars/swift5/model.mustache create mode 100644 src/main/resources/handlebars/swift5/modelArray.mustache create mode 100644 src/main/resources/handlebars/swift5/modelEnum.mustache create mode 100644 src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache create mode 100644 src/main/resources/handlebars/swift5/modelObject.mustache diff --git a/src/main/resources/handlebars/swift5/APIHelper.mustache b/src/main/resources/handlebars/swift5/APIHelper.mustache new file mode 100644 index 0000000000..81e7286d6d --- /dev/null +++ b/src/main/resources/handlebars/swift5/APIHelper.mustache @@ -0,0 +1,65 @@ +// APIHelper.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +public struct APIHelper { + public static func rejectNil(_ source: [String:Any?]) -> [String:Any]? { + let destination = source.reduce(into: [String: Any]()) { (result, item) in + if let value = item.value { + result[item.key] = value + } + } + + if destination.isEmpty { + return nil + } + return destination + } + + public static func rejectNilHeaders(_ source: [String:Any?]) -> [String:String] { + return source.reduce(into: [String: String]()) { (result, item) in + if let collection = item.value as? Array { + result[item.key] = collection.filter({ $0 != nil }).map{ "\($0!)" }.joined(separator: ",") + } else if let value: Any = item.value { + result[item.key] = "\(value)" + } + } + } + + public static func convertBoolToString(_ source: [String: Any]?) -> [String:Any]? { + guard let source = source else { + return nil + } + + return source.reduce(into: [String: Any](), { (result, item) in + switch item.value { + case let x as Bool: + result[item.key] = x.description + default: + result[item.key] = item.value + } + }) + } + + + public static func mapValuesToQueryItems(_ source: [String:Any?]) -> [URLQueryItem]? { + let destination = source.filter({ $0.value != nil}).reduce(into: [URLQueryItem]()) { (result, item) in + if let collection = item.value as? Array { + let value = collection.filter({ $0 != nil }).map({"\($0!)"}).joined(separator: ",") + result.append(URLQueryItem(name: item.key, value: value)) + } else if let value = item.value { + result.append(URLQueryItem(name: item.key, value: "\(value)")) + } + } + + if destination.isEmpty { + return nil + } + return destination + } +} + diff --git a/src/main/resources/handlebars/swift5/APIs.mustache b/src/main/resources/handlebars/swift5/APIs.mustache new file mode 100644 index 0000000000..f96d56963e --- /dev/null +++ b/src/main/resources/handlebars/swift5/APIs.mustache @@ -0,0 +1,61 @@ +// APIs.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +open class {{projectName}}API { + public static var basePath = "{{{basePath}}}" + public static var credential: URLCredential? + public static var customHeaders: [String:String] = [:] + public static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory() +} + +open class RequestBuilder { + var credential: URLCredential? + var headers: [String:String] + public let parameters: [String:Any]? + public let isBody: Bool + public let method: String + public let URLString: String + + /// Optional block to obtain a reference to the request's progress instance when available. + public var onProgressReady: ((Progress) -> ())? + + required public init(method: String, URLString: String, parameters: [String:Any]?, isBody: Bool, headers: [String:String] = [:]) { + self.method = method + self.URLString = URLString + self.parameters = parameters + self.isBody = isBody + self.headers = headers + + addHeaders({{projectName}}API.customHeaders) + } + + open func addHeaders(_ aHeaders:[String:String]) { + for (header, value) in aHeaders { + headers[header] = value + } + } + + open func execute(_ completion: @escaping (_ response: Response?, _ error: Error?) -> Void) { } + + public func addHeader(name: String, value: String) -> Self { + if !value.isEmpty { + headers[name] = value + } + return self + } + + open func addCredential() -> Self { + self.credential = {{projectName}}API.credential + return self + } +} + +public protocol RequestBuilderFactory { + func getNonDecodableBuilder() -> RequestBuilder.Type + func getBuilder() -> RequestBuilder.Type +} diff --git a/src/main/resources/handlebars/swift5/AlamofireImplementations.mustache b/src/main/resources/handlebars/swift5/AlamofireImplementations.mustache new file mode 100644 index 0000000000..f072650e79 --- /dev/null +++ b/src/main/resources/handlebars/swift5/AlamofireImplementations.mustache @@ -0,0 +1,422 @@ +// AlamofireImplementations.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import Alamofire + +class AlamofireRequestBuilderFactory: RequestBuilderFactory { + func getNonDecodableBuilder() -> RequestBuilder.Type { + return AlamofireRequestBuilder.self + } + + func getBuilder() -> RequestBuilder.Type { + return AlamofireDecodableRequestBuilder.self + } +} + +// Store manager to retain its reference +private var managerStore: [String: Alamofire.SessionManager] = [:] + +// Sync queue to manage safe access to the store manager +private let syncQueue = DispatchQueue(label: "thread-safe-sync-queue", attributes: .concurrent) + +open class AlamofireRequestBuilder: RequestBuilder { + required public init(method: String, URLString: String, parameters: [String : Any]?, isBody: Bool, headers: [String : String] = [:]) { + super.init(method: method, URLString: URLString, parameters: parameters, isBody: isBody, headers: headers) + } + + /** + May be overridden by a subclass if you want to control the session + configuration. + */ + open func createSessionManager() -> Alamofire.SessionManager { + let configuration = URLSessionConfiguration.default + configuration.httpAdditionalHeaders = buildHeaders() + return Alamofire.SessionManager(configuration: configuration) + } + + /** + May be overridden by a subclass if you want to control the Content-Type + that is given to an uploaded form part. + + Return nil to use the default behavior (inferring the Content-Type from + the file extension). Return the desired Content-Type otherwise. + */ + open func contentTypeForFormPart(fileURL: URL) -> String? { + return nil + } + + /** + May be overridden by a subclass if you want to control the request + configuration (e.g. to override the cache policy). + */ + open func makeRequest(manager: SessionManager, method: HTTPMethod, encoding: ParameterEncoding, headers: [String:String]) -> DataRequest { + return manager.request(URLString, method: method, parameters: parameters, encoding: encoding, headers: headers) + } + + override open func execute(_ completion: @escaping (_ response: Response?, _ error: Error?) -> Void) { + let managerId:String = UUID().uuidString + // Create a new manager for each request to customize its request header + let manager = createSessionManager() + syncQueue.async(flags: .barrier) { + managerStore[managerId] = manager + } + + let encoding:ParameterEncoding = isBody ? JSONDataEncoding() : URLEncoding() + + let xMethod = Alamofire.HTTPMethod(rawValue: method) + let fileKeys = parameters == nil ? [] : parameters!.filter { $1 is NSURL } + .map { $0.0 } + + if fileKeys.count > 0 { + manager.upload(multipartFormData: { mpForm in + for (k, v) in self.parameters! { + switch v { + case let fileURL as URL: + if let mimeType = self.contentTypeForFormPart(fileURL: fileURL) { + mpForm.append(fileURL, withName: k, fileName: fileURL.lastPathComponent, mimeType: mimeType) + } + else { + mpForm.append(fileURL, withName: k) + } + case let string as String: + mpForm.append(string.data(using: String.Encoding.utf8)!, withName: k) + case let number as NSNumber: + mpForm.append(number.stringValue.data(using: String.Encoding.utf8)!, withName: k) + default: + fatalError("Unprocessable value \(v) with key \(k)") + } + } + }, to: URLString, method: xMethod!, headers: nil, encodingCompletion: { encodingResult in + switch encodingResult { + case .success(let upload, _, _): + if let onProgressReady = self.onProgressReady { + onProgressReady(upload.uploadProgress) + } + self.processRequest(request: upload, managerId, completion) + case .failure(let encodingError): + completion(nil, ErrorResponse.error(415, nil, encodingError)) + } + }) + } else { + let request = makeRequest(manager: manager, method: xMethod!, encoding: encoding, headers: headers) + if let onProgressReady = self.onProgressReady { + onProgressReady(request.progress) + } + processRequest(request: request, managerId, completion) + } + + } + + fileprivate func processRequest(request: DataRequest, _ managerId: String, _ completion: @escaping (_ response: Response?, _ error: Error?) -> Void) { + if let credential = self.credential { + request.authenticate(usingCredential: credential) + } + + let cleanupRequest = { + syncQueue.async(flags: .barrier) { + _ = managerStore.removeValue(forKey: managerId) + } + } + + let validatedRequest = request.validate() + + switch T.self { + case is String.Type: + validatedRequest.responseString(completionHandler: { (stringResponse) in + cleanupRequest() + + if stringResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error!) + ) + return + } + + completion( + Response( + response: stringResponse.response!, + body: ((stringResponse.result.value ?? "") as! T) + ), + nil + ) + }) + case is URL.Type: + validatedRequest.responseData(completionHandler: { (dataResponse) in + cleanupRequest() + + do { + + guard !dataResponse.result.isFailure else { + throw DownloadException.responseFailed + } + + guard let data = dataResponse.data else { + throw DownloadException.responseDataMissing + } + + guard let request = request.request else { + throw DownloadException.requestMissing + } + + let fileManager = FileManager.default + let urlRequest = try request.asURLRequest() + let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0] + let requestURL = try self.getURL(from: urlRequest) + + var requestPath = try self.getPath(from: requestURL) + + if let headerFileName = self.getFileName(fromContentDisposition: dataResponse.response?.allHeaderFields["Content-Disposition"] as? String) { + requestPath = requestPath.appending("/\(headerFileName)") + } + + let filePath = documentsDirectory.appendingPathComponent(requestPath) + let directoryPath = filePath.deletingLastPathComponent().path + + try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil) + try data.write(to: filePath, options: .atomic) + + completion( + Response( + response: dataResponse.response!, + body: (filePath as! T) + ), + nil + ) + + } catch let requestParserError as DownloadException { + completion(nil, ErrorResponse.error(400, dataResponse.data, requestParserError)) + } catch let error { + completion(nil, ErrorResponse.error(400, dataResponse.data, error)) + } + return + }) + case is Void.Type: + validatedRequest.responseData(completionHandler: { (voidResponse) in + cleanupRequest() + + if voidResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!) + ) + return + } + + completion( + Response( + response: voidResponse.response!, + body: nil), + nil + ) + }) + default: + validatedRequest.responseData(completionHandler: { (dataResponse) in + cleanupRequest() + + if dataResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!) + ) + return + } + + completion( + Response( + response: dataResponse.response!, + body: (dataResponse.data as! T) + ), + nil + ) + }) + } + } + + open func buildHeaders() -> [String: String] { + var httpHeaders = SessionManager.defaultHTTPHeaders + for (key, value) in self.headers { + httpHeaders[key] = value + } + return httpHeaders + } + + fileprivate func getFileName(fromContentDisposition contentDisposition : String?) -> String? { + + guard let contentDisposition = contentDisposition else { + return nil + } + + let items = contentDisposition.components(separatedBy: ";") + + var filename : String? = nil + + for contentItem in items { + + let filenameKey = "filename=" + guard let range = contentItem.range(of: filenameKey) else { + break + } + + filename = contentItem + return filename? + .replacingCharacters(in: range, with:"") + .replacingOccurrences(of: "\"", with: "") + .trimmingCharacters(in: .whitespacesAndNewlines) + } + + return filename + + } + + fileprivate func getPath(from url : URL) throws -> String { + + guard var path = URLComponents(url: url, resolvingAgainstBaseURL: true)?.path else { + throw DownloadException.requestMissingPath + } + + if path.hasPrefix("/") { + path.remove(at: path.startIndex) + } + + return path + + } + + fileprivate func getURL(from urlRequest : URLRequest) throws -> URL { + + guard let url = urlRequest.url else { + throw DownloadException.requestMissingURL + } + + return url + } + +} + +fileprivate enum DownloadException : Error { + case responseDataMissing + case responseFailed + case requestMissing + case requestMissingPath + case requestMissingURL +} + +public enum AlamofireDecodableRequestBuilderError: Error { + case emptyDataResponse + case nilHTTPResponse + case jsonDecoding(DecodingError) + case generalError(Error) +} + +open class AlamofireDecodableRequestBuilder: AlamofireRequestBuilder { + + override fileprivate func processRequest(request: DataRequest, _ managerId: String, _ completion: @escaping (_ response: Response?, _ error: Error?) -> Void) { + if let credential = self.credential { + request.authenticate(usingCredential: credential) + } + + let cleanupRequest = { + syncQueue.async(flags: .barrier) { + _ = managerStore.removeValue(forKey: managerId) + } + } + + let validatedRequest = request.validate() + + switch T.self { + case is String.Type: + validatedRequest.responseString(completionHandler: { (stringResponse) in + cleanupRequest() + + if stringResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error!) + ) + return + } + + completion( + Response( + response: stringResponse.response!, + body: ((stringResponse.result.value ?? "") as! T) + ), + nil + ) + }) + case is Void.Type: + validatedRequest.responseData(completionHandler: { (voidResponse) in + cleanupRequest() + + if voidResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!) + ) + return + } + + completion( + Response( + response: voidResponse.response!, + body: nil), + nil + ) + }) + case is Data.Type: + validatedRequest.responseData(completionHandler: { (dataResponse) in + cleanupRequest() + + if dataResponse.result.isFailure { + completion( + nil, + ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!) + ) + return + } + + completion( + Response( + response: dataResponse.response!, + body: (dataResponse.data as! T) + ), + nil + ) + }) + default: + validatedRequest.responseData(completionHandler: { (dataResponse: DataResponse) in + cleanupRequest() + + guard dataResponse.result.isSuccess else { + completion(nil, ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)) + return + } + + guard let data = dataResponse.data, !data.isEmpty else { + completion(nil, ErrorResponse.error(-1, nil, AlamofireDecodableRequestBuilderError.emptyDataResponse)) + return + } + + guard let httpResponse = dataResponse.response else { + completion(nil, ErrorResponse.error(-2, nil, AlamofireDecodableRequestBuilderError.nilHTTPResponse)) + return + } + + var responseObj: Response? = nil + + let decodeResult: (decodableObj: T?, error: Error?) = CodableHelper.decode(T.self, from: data) + if decodeResult.error == nil { + responseObj = Response(response: httpResponse, body: decodeResult.decodableObj) + } + + completion(responseObj, decodeResult.error) + }) + } + } + +} diff --git a/src/main/resources/handlebars/swift5/Cartfile.mustache b/src/main/resources/handlebars/swift5/Cartfile.mustache new file mode 100644 index 0000000000..f71be5049a --- /dev/null +++ b/src/main/resources/handlebars/swift5/Cartfile.mustache @@ -0,0 +1,3 @@ +github "Alamofire/Alamofire" ~> 4.9.0{{#usePromiseKit}} +github "mxcl/PromiseKit" ~> 4.4{{/usePromiseKit}}{{#useRxSwift}} +github "ReactiveX/RxSwift" ~> 4.0{{/useRxSwift}} diff --git a/src/main/resources/handlebars/swift5/CodableHelper.mustache b/src/main/resources/handlebars/swift5/CodableHelper.mustache new file mode 100644 index 0000000000..c3039419df --- /dev/null +++ b/src/main/resources/handlebars/swift5/CodableHelper.mustache @@ -0,0 +1,93 @@ +// +// CodableHelper.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +public typealias EncodeResult = (data: Data?, error: Error?) + +enum DateError: String, Error { + case invalidDate +} + +open class CodableHelper { + + public static var dateformatter: DateFormatter? + + open class func decode(_ type: T.Type, from data: Data) -> (decodableObj: T?, error: Error?) where T : Decodable { + var returnedDecodable: T? = nil + var returnedError: Error? = nil + + let decoder = JSONDecoder() + + if let df = self.dateformatter { + decoder.dateDecodingStrategy = .formatted(df) + } else { + decoder.dataDecodingStrategy = .base64 + decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in + let container = try decoder.singleValueContainer() + let dateStr = try container.decode(String.self) + + let formatters = [ + "yyyy-MM-dd", + "yyyy-MM-dd'T'HH:mm:ssZZZZZ", + "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", + "yyyy-MM-dd'T'HH:mm:ss'Z'", + "yyyy-MM-dd'T'HH:mm:ss.SSS", + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "yyyy-MM-dd HH:mm:ss" + ].map { (format: String) -> DateFormatter in + let formatter = DateFormatter() + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.dateFormat = format + return formatter + } + + for formatter in formatters { + + if let date = formatter.date(from: dateStr) { + return date + } + } + + throw DateError.invalidDate + }) + } + + do { + returnedDecodable = try decoder.decode(type, from: data) + } catch { + returnedError = error + } + + return (returnedDecodable, returnedError) + } + + open class func encode(_ value: T, prettyPrint: Bool = false) -> EncodeResult where T : Encodable { + var returnedData: Data? + var returnedError: Error? = nil + + let encoder = JSONEncoder() + if prettyPrint { + encoder.outputFormatting = .prettyPrinted + } + encoder.dataEncodingStrategy = .base64 + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" + encoder.dateEncodingStrategy = .formatted(formatter) + + do { + returnedData = try encoder.encode(value) + } catch { + returnedError = error + } + + return (returnedData, returnedError) + } +} diff --git a/src/main/resources/handlebars/swift5/Configuration.mustache b/src/main/resources/handlebars/swift5/Configuration.mustache new file mode 100644 index 0000000000..139bced052 --- /dev/null +++ b/src/main/resources/handlebars/swift5/Configuration.mustache @@ -0,0 +1,15 @@ +// Configuration.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +open class Configuration { + + // This value is used to configure the date formatter that is used to serialize dates into JSON format. + // You must set it prior to encoding any dates, and it will only be read once. + public static var dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" + +} \ No newline at end of file diff --git a/src/main/resources/handlebars/swift5/Extensions.mustache b/src/main/resources/handlebars/swift5/Extensions.mustache new file mode 100644 index 0000000000..d5a43b407d --- /dev/null +++ b/src/main/resources/handlebars/swift5/Extensions.mustache @@ -0,0 +1,186 @@ +// Extensions.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import Alamofire{{#usePromiseKit}} +import PromiseKit{{/usePromiseKit}} + +extension Bool: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Float: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Int: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension Int32: JSONEncodable { + func encodeToJSON() -> Any { return NSNumber(value: self as Int32) } +} + +extension Int64: JSONEncodable { + func encodeToJSON() -> Any { return NSNumber(value: self as Int64) } +} + +extension Double: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +extension String: JSONEncodable { + func encodeToJSON() -> Any { return self as Any } +} + +private func encodeIfPossible(_ object: T) -> Any { + if let encodableObject = object as? JSONEncodable { + return encodableObject.encodeToJSON() + } else { + return object as Any + } +} + +extension Array: JSONEncodable { + func encodeToJSON() -> Any { + return self.map(encodeIfPossible) + } +} + +extension Dictionary: JSONEncodable { + func encodeToJSON() -> Any { + var dictionary = [AnyHashable: Any]() + for (key, value) in self { + dictionary[key] = encodeIfPossible(value) + } + return dictionary as Any + } +} + +extension Data: JSONEncodable { + func encodeToJSON() -> Any { + return self.base64EncodedString(options: Data.Base64EncodingOptions()) + } +} + +private let dateFormatter: DateFormatter = { + let fmt = DateFormatter() + fmt.dateFormat = Configuration.dateFormat + fmt.locale = Locale(identifier: "en_US_POSIX") + return fmt +}() + +extension Date: JSONEncodable { + func encodeToJSON() -> Any { + return dateFormatter.string(from: self) as Any + } +} + +extension UUID: JSONEncodable { + func encodeToJSON() -> Any { + return self.uuidString + } +} + +extension String: CodingKey { + + public var stringValue: String { + return self + } + + public init?(stringValue: String) { + self.init(stringLiteral: stringValue) + } + + public var intValue: Int? { + return nil + } + + public init?(intValue: Int) { + return nil + } + +} + +extension KeyedEncodingContainerProtocol { + + public mutating func encodeArray(_ values: [T], forKey key: Self.Key) throws where T : Encodable { + var arrayContainer = nestedUnkeyedContainer(forKey: key) + try arrayContainer.encode(contentsOf: values) + } + + public mutating func encodeArrayIfPresent(_ values: [T]?, forKey key: Self.Key) throws where T : Encodable { + if let values = values { + try encodeArray(values, forKey: key) + } + } + + public mutating func encodeMap(_ pairs: [Self.Key: T]) throws where T : Encodable { + for (key, value) in pairs { + try encode(value, forKey: key) + } + } + + public mutating func encodeMapIfPresent(_ pairs: [Self.Key: T]?) throws where T : Encodable { + if let pairs = pairs { + try encodeMap(pairs) + } + } + +} + +extension KeyedDecodingContainerProtocol { + + public func decodeArray(_ type: T.Type, forKey key: Self.Key) throws -> [T] where T : Decodable { + var tmpArray = [T]() + + var nestedContainer = try nestedUnkeyedContainer(forKey: key) + while !nestedContainer.isAtEnd { + let arrayValue = try nestedContainer.decode(T.self) + tmpArray.append(arrayValue) + } + + return tmpArray + } + + public func decodeArrayIfPresent(_ type: T.Type, forKey key: Self.Key) throws -> [T]? where T : Decodable { + var tmpArray: [T]? = nil + + if contains(key) { + tmpArray = try decodeArray(T.self, forKey: key) + } + + return tmpArray + } + + public func decodeMap(_ type: T.Type, excludedKeys: Set) throws -> [Self.Key: T] where T : Decodable { + var map: [Self.Key : T] = [:] + + for key in allKeys { + if !excludedKeys.contains(key) { + let value = try decode(T.self, forKey: key) + map[key] = value + } + } + + return map + } + +} + +{{#usePromiseKit}}extension RequestBuilder { + public func execute() -> Promise> { + let deferred = Promise>.pending() + self.execute { (response: Response?, error: Error?) in + if let response = response { + deferred.fulfill(response) + } else { + deferred.reject(error!) + } + } + return deferred.promise + } +}{{/usePromiseKit}} diff --git a/src/main/resources/handlebars/swift5/JSONEncodableEncoding.mustache b/src/main/resources/handlebars/swift5/JSONEncodableEncoding.mustache new file mode 100644 index 0000000000..472e955ee8 --- /dev/null +++ b/src/main/resources/handlebars/swift5/JSONEncodableEncoding.mustache @@ -0,0 +1,54 @@ +// +// JSONDataEncoding.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import Alamofire + +public struct JSONDataEncoding: ParameterEncoding { + + // MARK: Properties + + private static let jsonDataKey = "jsonData" + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. This should have a single key/value + /// pair with "jsonData" as the key and a Data object as the value. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let jsonData = parameters?[JSONDataEncoding.jsonDataKey] as? Data, !jsonData.isEmpty else { + return urlRequest + } + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = jsonData + + return urlRequest + } + + public static func encodingParameters(jsonData: Data?) -> Parameters? { + var returnedParams: Parameters? = nil + if let jsonData = jsonData, !jsonData.isEmpty { + var params = Parameters() + params[jsonDataKey] = jsonData + returnedParams = params + } + return returnedParams + } + +} diff --git a/src/main/resources/handlebars/swift5/JSONEncodingHelper.mustache b/src/main/resources/handlebars/swift5/JSONEncodingHelper.mustache new file mode 100644 index 0000000000..19ee06b1f4 --- /dev/null +++ b/src/main/resources/handlebars/swift5/JSONEncodingHelper.mustache @@ -0,0 +1,43 @@ +// +// JSONEncodingHelper.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import Alamofire + +open class JSONEncodingHelper { + + open class func encodingParameters(forEncodableObject encodableObj: T?) -> Parameters? { + var params: Parameters? = nil + + // Encode the Encodable object + if let encodableObj = encodableObj { + let encodeResult = CodableHelper.encode(encodableObj, prettyPrint: true) + if encodeResult.error == nil { + params = JSONDataEncoding.encodingParameters(jsonData: encodeResult.data) + } + } + + return params + } + + open class func encodingParameters(forEncodableObject encodableObj: Any?) -> Parameters? { + var params: Parameters? = nil + + if let encodableObj = encodableObj { + do { + let data = try JSONSerialization.data(withJSONObject: encodableObj, options: .prettyPrinted) + params = JSONDataEncoding.encodingParameters(jsonData: data) + } catch { + print(error) + return nil + } + } + + return params + } + +} diff --git a/src/main/resources/handlebars/swift5/JSONValue.mustache b/src/main/resources/handlebars/swift5/JSONValue.mustache new file mode 100644 index 0000000000..21a93ac8bb --- /dev/null +++ b/src/main/resources/handlebars/swift5/JSONValue.mustache @@ -0,0 +1,99 @@ +// +// JSONEncodingHelper.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + + +public enum JSONValue: Codable, Equatable { + case string(String) + case int(Int) + case double(Double) + case bool(Bool) + case object([String: JSONValue]) + case array([JSONValue]) + case null + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .string(let string): try container.encode(string) + case .int(let int): try container.encode(int) + case .double(let double): try container.encode(double) + case .bool(let bool): try container.encode(bool) + case .object(let object): try container.encode(object) + case .array(let array): try container.encode(array) + case .null: try container.encode(Optional.none) + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + self = try ((try? container.decode(String.self)).map(JSONValue.string)) + .or((try? container.decode(Int.self)).map(JSONValue.int)) + .or((try? container.decode(Double.self)).map(JSONValue.double)) + .or((try? container.decode(Bool.self)).map(JSONValue.bool)) + .or((try? container.decode([String: JSONValue].self)).map(JSONValue.object)) + .or((try? container.decode([JSONValue].self)).map(JSONValue.array)) + .or((container.decodeNil() ? .some(JSONValue.null) : .none)) + .resolve( + with: DecodingError.typeMismatch( + JSONValue.self, + DecodingError.Context( + codingPath: container.codingPath, + debugDescription: "Not a JSON value" + ) + ) + ) + } + +} + +extension JSONValue: ExpressibleByStringLiteral { + public init(stringLiteral value: String) { + self = .string(value) + } +} +extension JSONValue: ExpressibleByIntegerLiteral { + public init(integerLiteral value: Int) { + self = .int(value) + } +} +extension JSONValue: ExpressibleByFloatLiteral { + public init(floatLiteral value: Double) { + self = .double(value) + } +} +extension JSONValue: ExpressibleByBooleanLiteral { + public init(booleanLiteral value: Bool) { + self = .bool(value) + } +} +extension JSONValue: ExpressibleByDictionaryLiteral { + public init(dictionaryLiteral elements: (String, JSONValue)...) { + self = .object([String: JSONValue](uniqueKeysWithValues: elements)) + } +} +extension JSONValue: ExpressibleByArrayLiteral { + public init(arrayLiteral elements: JSONValue...) { + self = .array(elements) + } +} + +fileprivate extension Optional { + func or(_ other: Optional) -> Optional { + switch self { + case .none: return other + case .some: return self + } + } + func resolve(with error: @autoclosure () -> Error) throws -> Wrapped { + switch self { + case .none: throw error() + case .some(let wrapped): return wrapped + } + } +} diff --git a/src/main/resources/handlebars/swift5/Models.mustache b/src/main/resources/handlebars/swift5/Models.mustache new file mode 100644 index 0000000000..d7dfe637df --- /dev/null +++ b/src/main/resources/handlebars/swift5/Models.mustache @@ -0,0 +1,36 @@ +// Models.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +protocol JSONEncodable { + func encodeToJSON() -> Any +} + +public enum ErrorResponse : Error { + case error(Int, Data?, Error) +} + +open class Response { + public let statusCode: Int + public let header: [String: String] + public let body: T? + + public init(statusCode: Int, header: [String: String], body: T?) { + self.statusCode = statusCode + self.header = header + self.body = body + } + + public convenience init(response: HTTPURLResponse, body: T?) { + let rawHeader = response.allHeaderFields + var header = [String:String]() + for case let (key, value) as (String, String) in rawHeader { + header[key] = value + } + self.init(statusCode: response.statusCode, header: header, body: body) + } +} diff --git a/src/main/resources/handlebars/swift5/Podspec.mustache b/src/main/resources/handlebars/swift5/Podspec.mustache new file mode 100644 index 0000000000..855f1c96a7 --- /dev/null +++ b/src/main/resources/handlebars/swift5/Podspec.mustache @@ -0,0 +1,22 @@ +Pod::Spec.new do |s| + s.name = '{{projectName}}'{{#projectDescription}} + s.summary = '{{projectDescription}}'{{/projectDescription}} + s.ios.deployment_target = '9.0' + s.osx.deployment_target = '10.11' + s.tvos.deployment_target = '9.0' + s.version = '{{#podVersion}}{{podVersion}}{{/podVersion}}{{^podVersion}}0.0.1{{/podVersion}}' + s.source = {{#podSource}}{{& podSource}}{{/podSource}}{{^podSource}}{ :git => 'git@github.com:swagger-api/swagger-mustache.git', :tag => 'v1.0.0' }{{/podSource}}{{#podAuthors}} + s.authors = '{{podAuthors}}'{{/podAuthors}}{{#podSocialMediaURL}} + s.social_media_url = '{{podSocialMediaURL}}'{{/podSocialMediaURL}}{{#podDocsetURL}} + s.docset_url = '{{podDocsetURL}}'{{/podDocsetURL}} + s.license = {{#podLicense}}{{& podLicense}}{{/podLicense}}{{^podLicense}}'Proprietary'{{/podLicense}}{{#podHomepage}} + s.homepage = '{{podHomepage}}'{{/podHomepage}}{{#podSummary}} + s.summary = '{{podSummary}}'{{/podSummary}}{{#podDescription}} + s.description = '{{podDescription}}'{{/podDescription}}{{#podScreenshots}} + s.screenshots = {{& podScreenshots}}{{/podScreenshots}}{{#podDocumentationURL}} + s.documentation_url = '{{podDocumentationURL}}'{{/podDocumentationURL}} + s.source_files = '{{projectName}}/Classes/**/*.swift'{{#usePromiseKit}} + s.dependency 'PromiseKit/CorePromise', '~> 4.4.0'{{/usePromiseKit}}{{#useRxSwift}} + s.dependency 'RxSwift', '~> 4.0'{{/useRxSwift}} + s.dependency 'Alamofire', '~> 4.9.0' +end diff --git a/src/main/resources/handlebars/swift5/README.mustache b/src/main/resources/handlebars/swift5/README.mustache new file mode 100644 index 0000000000..0739f5acb3 --- /dev/null +++ b/src/main/resources/handlebars/swift5/README.mustache @@ -0,0 +1,65 @@ +# Swift5 API client for {{packageName}} + +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +## Overview +This API client was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [swagger-spec](https://github.com/swagger-api/swagger-spec) from a remote server, you can easily generate an API client. + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Installation +Put the package under your project folder and add the following in import: +``` + "./{{packageName}}" +``` + +## 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}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} + +## 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}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/src/main/resources/handlebars/swift5/_param.mustache b/src/main/resources/handlebars/swift5/_param.mustache new file mode 100644 index 0000000000..5caacbc600 --- /dev/null +++ b/src/main/resources/handlebars/swift5/_param.mustache @@ -0,0 +1 @@ +"{{baseName}}": {{paramName}}{{^isEnum}}{{#isInteger}}{{^required}}?{{/required}}.encodeToJSON(){{/isInteger}}{{#isLong}}{{^required}}?{{/required}}.encodeToJSON(){{/isLong}}{{/isEnum}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}.rawValue{{/isContainer}}{{/isEnum}}{{#isDate}}{{^required}}?{{/required}}.encodeToJSON(){{/isDate}}{{#isDateTime}}{{^required}}?{{/required}}.encodeToJSON(){{/isDateTime}} \ No newline at end of file diff --git a/src/main/resources/handlebars/swift5/api.mustache b/src/main/resources/handlebars/swift5/api.mustache new file mode 100644 index 0000000000..891657b00f --- /dev/null +++ b/src/main/resources/handlebars/swift5/api.mustache @@ -0,0 +1,162 @@ +{{#operations}}// +// {{classname}}.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation +import Alamofire{{#usePromiseKit}} +import PromiseKit{{/usePromiseKit}}{{#useRxSwift}} +import RxSwift{{/useRxSwift}} + +{{#swiftUseApiNamespace}} +extension {{projectName}}API { +{{/swiftUseApiNamespace}} + +{{#description}} +/** {{description}} */{{/description}} +open class {{classname}} { +{{#operation}} + {{#allParams}} + {{#isEnum}} + /** + * enum for parameter {{paramName}} + */ + public enum {{enumName}}_{{operationId}}: {{^isContainer}}{{{dataType}}}{{/isContainer}}{{#isContainer}}String{{/isContainer}} { {{#allowableValues}}{{#enumVars}} + case {{name}} = {{#isContainer}}"{{/isContainer}}{{#isString}}"{{/isString}}{{{value}}}{{#isString}}"{{/isString}}{{#isContainer}}"{{/isContainer}}{{/enumVars}}{{/allowableValues}} + } + + {{/isEnum}} + {{/allParams}} + /** + {{#summary}} + {{{summary}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - parameter completion: completion handler to receive the data and the error objects + */ + open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#hasParams}}, {{/hasParams}}completion: @escaping ((_ data: {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}?,_ error: Error?) -> Void)) { + {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).execute { (response, error) -> Void in + {{#returnType}} + completion(response?.body, error) + {{/returnType}} + {{^returnType}} + if error == nil { + completion((), error) + } else { + completion(nil, error) + } + {{/returnType}} + } + } + +{{#usePromiseKit}} + /** + {{#summary}} + {{{summary}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - returns: Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + open class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> { + let deferred = Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.pending() + {{operationId}}({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { data, error in + if let error = error { + deferred.reject(error) + } else { + deferred.fulfill(data!) + } + } + return deferred.promise + } +{{/usePromiseKit}} +{{#useRxSwift}} + /** + {{#summary}} + {{{summary}}} + {{/summary}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - returns: Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + */ + open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> { + return Observable.create { observer -> Disposable in + {{operationId}}({{#allParams}}{{paramName}}: {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { data, error in + if let error = error { + observer.on(.error(error)) + } else { + observer.on(.next(data!)) + } + observer.on(.completed) + } + return Disposables.create() + } + } +{{/useRxSwift}} + + /** + {{#summary}} + {{{summary}}} + {{/summary}} + - {{httpMethod}} {{{path}}}{{#notes}} + - {{{notes}}}{{/notes}}{{#subresourceOperation}} + - subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}} + - defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}} + - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: + - type: {{type}}{{#keyParamName}} {{keyParamName}} {{#isKeyInQuery}}(QUERY){{/isKeyInQuery}}{{#isKeyInHeaer}}(HEADER){{/isKeyInHeaer}}{{/keyParamName}} + - name: {{name}}{{/authMethods}}{{#responseHeaders}} + - responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}} + - examples: {{{examples}}}{{/examples}}{{#externalDocs}} + - externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}} + {{/hasParams}}{{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + + - returns: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{description}} + */ + open class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> { + {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{^secondaryParam}}var{{/secondaryParam}}{{/pathParams}} path = "{{{path}}}"{{#pathParams}} + let {{paramName}}PreEscape = "\({{paramName}}{{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}})" + let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" + path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + let URLString = {{projectName}}API.basePath + path + {{#bodyParam}} + let parameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) + {{/bodyParam}} + {{^bodyParam}} + {{#hasFormParams}} + let formParams: [String:Any?] = [ + {{#formParams}} + {{> _param}}{{#hasMore}},{{/hasMore}} + {{/formParams}} + ] + + let nonNullParameters = APIHelper.rejectNil(formParams) + let parameters = APIHelper.convertBoolToString(nonNullParameters) + {{/hasFormParams}} + {{^hasFormParams}} + let parameters: [String:Any]? = nil + {{/hasFormParams}} + {{/bodyParam}}{{#hasQueryParams}} + var url = URLComponents(string: URLString) + url?.queryItems = APIHelper.mapValuesToQueryItems([ + {{#queryParams}} + {{> _param}}{{#hasMore}}, {{/hasMore}} + {{/queryParams}} + ]){{/hasQueryParams}}{{^hasQueryParams}} + let url = URLComponents(string: URLString){{/hasQueryParams}}{{#headerParams}}{{^secondaryParam}} + let nillableHeaders: [String: Any?] = [{{/secondaryParam}} + {{> _param}}{{#hasMore}},{{/hasMore}}{{^hasMore}} + ] + let headerParameters = APIHelper.rejectNilHeaders(nillableHeaders){{/hasMore}}{{/headerParams}} + + let requestBuilder: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}API.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}} + + return requestBuilder.init(method: "{{httpMethod}}", URLString: (url?.string ?? URLString), parameters: parameters, isBody: {{hasBodyParam}}{{#headerParams}}{{^secondaryParam}}, headers: headerParameters{{/secondaryParam}}{{/headerParams}}) + } + +{{/operation}} +} +{{#swiftUseApiNamespace}} +} +{{/swiftUseApiNamespace}} +{{/operations}} diff --git a/src/main/resources/handlebars/swift5/git_push.sh.mustache b/src/main/resources/handlebars/swift5/git_push.sh.mustache new file mode 100755 index 0000000000..a2d7523483 --- /dev/null +++ b/src/main/resources/handlebars/swift5/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/src/main/resources/handlebars/swift5/gitignore.mustache b/src/main/resources/handlebars/swift5/gitignore.mustache new file mode 100644 index 0000000000..5e5d5cebcf --- /dev/null +++ b/src/main/resources/handlebars/swift5/gitignore.mustache @@ -0,0 +1,63 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots diff --git a/src/main/resources/handlebars/swift5/model.mustache b/src/main/resources/handlebars/swift5/model.mustache new file mode 100644 index 0000000000..189acedc53 --- /dev/null +++ b/src/main/resources/handlebars/swift5/model.mustache @@ -0,0 +1,25 @@ +{{#models}}{{#model}}// +// {{classname}}.swift +// +// Generated by swagger-codegen +// https://github.com/swagger-api/swagger-codegen +// + +import Foundation + +{{#description}} + +/** {{description}} */{{/description}} +{{#isArrayModel}} +{{> modelArray}} +{{/isArrayModel}} +{{^isArrayModel}} +{{#isEnum}} +{{> modelEnum}} +{{/isEnum}} +{{^isEnum}} +{{> modelObject}} +{{/isEnum}} +{{/isArrayModel}} +{{/model}} +{{/models}} diff --git a/src/main/resources/handlebars/swift5/modelArray.mustache b/src/main/resources/handlebars/swift5/modelArray.mustache new file mode 100644 index 0000000000..843626158c --- /dev/null +++ b/src/main/resources/handlebars/swift5/modelArray.mustache @@ -0,0 +1 @@ +public typealias {{classname}} = {{parent}} \ No newline at end of file diff --git a/src/main/resources/handlebars/swift5/modelEnum.mustache b/src/main/resources/handlebars/swift5/modelEnum.mustache new file mode 100644 index 0000000000..0b5bebe0eb --- /dev/null +++ b/src/main/resources/handlebars/swift5/modelEnum.mustache @@ -0,0 +1,4 @@ +public enum {{classname}}: {{dataType}}, Codable { +{{#allowableValues}}{{#enumVars}} case {{name}} = "{{{value}}}" +{{/enumVars}}{{/allowableValues}} +} \ No newline at end of file diff --git a/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache b/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache new file mode 100644 index 0000000000..c713edb31e --- /dev/null +++ b/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache @@ -0,0 +1,3 @@ + public enum {{enumName}}: {{^isContainer}}{{datatype}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, Codable { {{#allowableValues}}{{#enumVars}} + case {{name}} = {{#isContainer}}"{{/isContainer}}{{#isString}}"{{/isString}}{{{value}}}{{#isString}}"{{/isString}}{{#isContainer}}"{{/isContainer}}{{/enumVars}}{{/allowableValues}} + } \ No newline at end of file diff --git a/src/main/resources/handlebars/swift5/modelObject.mustache b/src/main/resources/handlebars/swift5/modelObject.mustache new file mode 100644 index 0000000000..e187c49437 --- /dev/null +++ b/src/main/resources/handlebars/swift5/modelObject.mustache @@ -0,0 +1,82 @@ + +public struct {{classname}}: Codable { + +{{#allVars}} +{{#isEnum}} +{{> modelInlineEnumDeclaration}} +{{/isEnum}} +{{/allVars}} +{{#allVars}} +{{#isEnum}} + {{#description}}/** {{description}} */ + {{/description}}public var {{name}}: {{{datatypeWithEnum}}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}} +{{/isEnum}} +{{^isEnum}} + {{#description}}/** {{description}} */ + {{/description}}public var {{name}}: {{{datatype}}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#objcCompatible}}{{#vendorExtensions.x-swift-optional-scalar}} + public var {{name}}Num: NSNumber? { + get { + return {{name}}.map({ return NSNumber(value: $0) }) + } + }{{/vendorExtensions.x-swift-optional-scalar}}{{/objcCompatible}} +{{/isEnum}} +{{/allVars}} + +{{#hasVars}} + public init({{#allVars}}{{name}}: {{{datatypeWithEnum}}}{{^required}}?{{/required}}{{#hasMore}}, {{/hasMore}}{{/allVars}}) { + {{#allVars}} + self.{{name}} = {{name}} + {{/allVars}} + } +{{/hasVars}} +{{#additionalPropertiesType}} + public var additionalProperties: [String:{{{additionalPropertiesType}}}] = [:] + + public subscript(key: String) -> {{{additionalPropertiesType}}}? { + get { + if let value = additionalProperties[key] { + return value + } + return nil + } + + set { + additionalProperties[key] = newValue + } + } + + // Encodable protocol methods + + public func encode(to encoder: Encoder) throws { + + var container = encoder.container(keyedBy: String.self) + + {{#allVars}} + try container.encode{{^required}}IfPresent{{/required}}({{{name}}}, forKey: "{{{baseName}}}") + {{/allVars}} + try container.encodeMap(additionalProperties) + } + + // Decodable protocol methods + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: String.self) + + {{#allVars}} + {{name}} = try container.decode{{^required}}IfPresent{{/required}}({{{datatypeWithEnum}}}.self, forKey: "{{{baseName}}}") + {{/allVars}} + var nonAdditionalPropertyKeys = Set() + {{#allVars}} + nonAdditionalPropertyKeys.insert("{{{baseName}}}") + {{/allVars}} + additionalProperties = try container.decodeMap({{{additionalPropertiesType}}}.self, excludedKeys: nonAdditionalPropertyKeys) + } + +{{/additionalPropertiesType}} +{{^additionalPropertiesType}}{{#vendorExtensions.x-codegen-has-escaped-property-names}} + public enum CodingKeys: String, CodingKey { {{#allVars}} + case {{name}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}{{/allVars}} + } +{{/vendorExtensions.x-codegen-has-escaped-property-names}}{{/additionalPropertiesType}} + +} From 362573a0c80d3ec7b66f7f10f3aa19af7aea5c1b Mon Sep 17 00:00:00 2001 From: HugoMario Date: Sun, 8 Dec 2019 03:40:16 -0500 Subject: [PATCH 12/17] use the right template location --- .../io/swagger/codegen/v3/generators/swift/Swift5Codegen.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java b/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java index 182e5a116f..b895ed3317 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/swift/Swift5Codegen.java @@ -94,7 +94,6 @@ public Swift5Codegen() { outputFolder = "generated-code" + File.separator + "swift"; modelTemplateFiles.put("model.mustache", ".swift"); apiTemplateFiles.put("api.mustache", ".swift"); - embeddedTemplateDir = templateDir = "swift5"; apiPackage = File.separator + "APIs"; modelPackage = File.separator + "Models"; @@ -245,6 +244,8 @@ public Swift5Codegen() { public void processOpts() { super.processOpts(); + embeddedTemplateDir = templateDir = getTemplateDir(); + // Setup project name if (additionalProperties.containsKey(PROJECT_NAME)) { setProjectName((String) additionalProperties.get(PROJECT_NAME)); From eb6e0da4c19ca90128e6fe1cfd578af3cfd17eec Mon Sep 17 00:00:00 2001 From: HugoMario Date: Sun, 8 Dec 2019 03:40:39 -0500 Subject: [PATCH 13/17] added swift5 generator class to meta file --- .../META-INF/services/io.swagger.codegen.v3.CodegenConfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/META-INF/services/io.swagger.codegen.v3.CodegenConfig b/src/main/resources/META-INF/services/io.swagger.codegen.v3.CodegenConfig index 334aa1dc10..4145ea3987 100644 --- a/src/main/resources/META-INF/services/io.swagger.codegen.v3.CodegenConfig +++ b/src/main/resources/META-INF/services/io.swagger.codegen.v3.CodegenConfig @@ -29,5 +29,6 @@ io.swagger.codegen.v3.generators.scala.ScalaClientCodegen io.swagger.codegen.v3.generators.scala.AkkaHttpServerCodegen io.swagger.codegen.v3.generators.swift.Swift3Codegen io.swagger.codegen.v3.generators.swift.Swift4Codegen +io.swagger.codegen.v3.generators.swift.Swift5Codegen io.swagger.codegen.v3.generators.typescript.TypeScriptAngularClientCodegen io.swagger.codegen.v3.generators.javascript.JavaScriptClientCodegen From 955112cb9de694a02b899bbdd68f4b49e32e8a94 Mon Sep 17 00:00:00 2001 From: HugoMario Date: Sun, 8 Dec 2019 04:14:12 -0500 Subject: [PATCH 14/17] tweaked model templates --- .../swift5/modelInlineEnumDeclaration.mustache | 2 +- .../resources/handlebars/swift5/modelObject.mustache | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache b/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache index c713edb31e..6c41f992ef 100644 --- a/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache +++ b/src/main/resources/handlebars/swift5/modelInlineEnumDeclaration.mustache @@ -1,3 +1,3 @@ public enum {{enumName}}: {{^isContainer}}{{datatype}}{{/isContainer}}{{#isContainer}}String{{/isContainer}}, Codable { {{#allowableValues}}{{#enumVars}} case {{name}} = {{#isContainer}}"{{/isContainer}}{{#isString}}"{{/isString}}{{{value}}}{{#isString}}"{{/isString}}{{#isContainer}}"{{/isContainer}}{{/enumVars}}{{/allowableValues}} - } \ No newline at end of file + } diff --git a/src/main/resources/handlebars/swift5/modelObject.mustache b/src/main/resources/handlebars/swift5/modelObject.mustache index e187c49437..92d2d1eb47 100644 --- a/src/main/resources/handlebars/swift5/modelObject.mustache +++ b/src/main/resources/handlebars/swift5/modelObject.mustache @@ -12,8 +12,10 @@ public struct {{classname}}: Codable { {{/description}}public var {{name}}: {{{datatypeWithEnum}}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}} {{/isEnum}} {{^isEnum}} - {{#description}}/** {{description}} */ - {{/description}}public var {{name}}: {{{datatype}}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#objcCompatible}}{{#vendorExtensions.x-swift-optional-scalar}} + {{#description}} + /** {{description}} */ + {{/description}} + public var {{name}}: {{{datatype}}}{{^required}}?{{/required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{#objcCompatible}}{{#vendorExtensions.x-swift-optional-scalar}} public var {{name}}Num: NSNumber? { get { return {{name}}.map({ return NSNumber(value: $0) }) @@ -73,10 +75,13 @@ public struct {{classname}}: Codable { } {{/additionalPropertiesType}} -{{^additionalPropertiesType}}{{#vendorExtensions.x-codegen-has-escaped-property-names}} +{{^additionalPropertiesType}} + +{{#vendorExtensions.x-codegen-has-escaped-property-names}} public enum CodingKeys: String, CodingKey { {{#allVars}} case {{name}}{{#vendorExtensions.x-codegen-escaped-property-name}} = "{{{baseName}}}"{{/vendorExtensions.x-codegen-escaped-property-name}}{{/allVars}} } {{/vendorExtensions.x-codegen-has-escaped-property-names}}{{/additionalPropertiesType}} } + From b78378a9a5059d872d38351244e29124792c0b6e Mon Sep 17 00:00:00 2001 From: HugoMario Date: Sun, 8 Dec 2019 16:15:47 -0500 Subject: [PATCH 15/17] fixed api template format --- .../resources/handlebars/swift5/api.mustache | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/resources/handlebars/swift5/api.mustache b/src/main/resources/handlebars/swift5/api.mustache index 891657b00f..ec80f5d57d 100644 --- a/src/main/resources/handlebars/swift5/api.mustache +++ b/src/main/resources/handlebars/swift5/api.mustache @@ -15,7 +15,10 @@ extension {{projectName}}API { {{/swiftUseApiNamespace}} {{#description}} -/** {{description}} */{{/description}} +/** + {{description}} + */ +{{/description}} open class {{classname}} { {{#operation}} {{#allParams}} @@ -32,8 +35,11 @@ open class {{classname}} { /** {{#summary}} {{{summary}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + {{/summary}} + + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} - parameter completion: completion handler to receive the data and the error objects */ open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#hasParams}}, {{/hasParams}}completion: @escaping ((_ data: {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}?,_ error: Error?) -> Void)) { @@ -55,8 +61,10 @@ open class {{classname}} { /** {{#summary}} {{{summary}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + {{/summary}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} - returns: Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> */ open class func {{operationId}}({{#allParams}} {{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> { @@ -75,8 +83,10 @@ open class {{classname}} { /** {{#summary}} {{{summary}}} - {{/summary}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + {{/summary}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} - returns: Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> */ open class func {{operationId}}({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Observable<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> { @@ -98,8 +108,9 @@ open class {{classname}} { {{#summary}} {{{summary}}} {{/summary}} - - {{httpMethod}} {{{path}}}{{#notes}} - - {{{notes}}}{{/notes}}{{#subresourceOperation}} + - {{httpMethod}} {{{path}}}{{^notes}} + - {{{notes}}}{{/notes}} + {{#subresourceOperation}} - subresourceOperation: {{subresourceOperation}}{{/subresourceOperation}}{{#defaultResponse}} - defaultResponse: {{defaultResponse}}{{/defaultResponse}}{{#authMethods}} - {{#isBasic}}BASIC{{/isBasic}}{{#isOAuth}}OAuth{{/isOAuth}}{{#isApiKey}}API Key{{/isApiKey}}: @@ -107,9 +118,10 @@ open class {{classname}} { - name: {{name}}{{/authMethods}}{{#responseHeaders}} - responseHeaders: {{responseHeaders}}{{/responseHeaders}}{{#examples}} - examples: {{{examples}}}{{/examples}}{{#externalDocs}} - - externalDocs: {{externalDocs}}{{/externalDocs}}{{#hasParams}} - {{/hasParams}}{{#allParams}} - - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}} + - externalDocs: {{externalDocs}}{{/externalDocs}} + {{#allParams}} + - parameter {{paramName}}: ({{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}}) {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} + {{/allParams}} - returns: RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{description}} */ @@ -117,17 +129,17 @@ open class {{classname}} { {{^pathParams}}let{{/pathParams}}{{#pathParams}}{{^secondaryParam}}var{{/secondaryParam}}{{/pathParams}} path = "{{{path}}}"{{#pathParams}} let {{paramName}}PreEscape = "\({{paramName}}{{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}})" let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "" - path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} + path = path.replacingOccurrences(of: "{{braces "left"}}{{baseName}}{{braces "right"}}", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}} let URLString = {{projectName}}API.basePath + path {{#bodyParam}} let parameters = JSONEncodingHelper.encodingParameters(forEncodableObject: {{paramName}}) {{/bodyParam}} {{^bodyParam}} - {{#hasFormParams}} + {{#hasFormParams}} let formParams: [String:Any?] = [ - {{#formParams}} - {{> _param}}{{#hasMore}},{{/hasMore}} - {{/formParams}} + {{#formParams}} + {{> _param}}{{#hasMore}},{{/hasMore}} + {{/formParams}} ] let nonNullParameters = APIHelper.rejectNil(formParams) From 652ca6f20cf973ee4c0daf3873efa8859eb8e9d4 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 12 Dec 2019 12:25:06 +0100 Subject: [PATCH 16/17] refs swagger-api/swagger-codegen#9421 - fix gradle build --- .gitignore | 8 -------- .../handlebars/Java/build.gradle.mustache | 6 +++--- .../handlebars/Java/gradle-wrapper.jar | Bin 0 -> 53639 bytes .../libraries/jersey2/build.gradle.mustache | 6 +++--- 4 files changed, 6 insertions(+), 14 deletions(-) create mode 100644 src/main/resources/handlebars/Java/gradle-wrapper.jar diff --git a/.gitignore b/.gitignore index 578d2fa3a3..18de241bc9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,14 +14,6 @@ # Mobile Tools for Java (J2ME) .mtj.tmp/ -# Package Files # -*.jar -*.war -*.ear -*.zip -*.tar.gz -*.rar - # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* diff --git a/src/main/resources/handlebars/Java/build.gradle.mustache b/src/main/resources/handlebars/Java/build.gradle.mustache index 8ea8389223..34cb09be17 100644 --- a/src/main/resources/handlebars/Java/build.gradle.mustache +++ b/src/main/resources/handlebars/Java/build.gradle.mustache @@ -132,13 +132,13 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" diff --git a/src/main/resources/handlebars/Java/gradle-wrapper.jar b/src/main/resources/handlebars/Java/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c6137b87896c8f70315ae454e00a969ef5f6019 GIT binary patch literal 53639 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 F{{tUq7iIte literal 0 HcmV?d00001 diff --git a/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache b/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache index f21044a155..759a1603bc 100644 --- a/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache +++ b/src/main/resources/handlebars/Java/libraries/jersey2/build.gradle.mustache @@ -134,17 +134,17 @@ dependencies { compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version", + compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/java8}} {{#supportJava6}} compile "commons-io:commons-io:$commons_io_version" compile "org.apache.commons:commons-lang3:$commons_lang3_version" {{/supportJava6}} {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version", + compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" {{/threetenbp}} {{^java8}} compile "com.brsanthu:migbase64:2.2" From 312a0324df0fe6a58834b87437d27224bb195959 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 12 Dec 2019 12:35:35 +0100 Subject: [PATCH 17/17] refs #527 - fix allOf discriminator processing --- .../io/swagger/codegen/v3/generators/DefaultCodegenConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java index 560864a033..b5750a3063 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java +++ b/src/main/java/io/swagger/codegen/v3/generators/DefaultCodegenConfig.java @@ -1324,7 +1324,7 @@ else if (schema instanceof ComposedSchema) { if(composed.getAllOf() != null) { for (Schema innerModel : composed.getAllOf()) { if (codegenModel.discriminator == null) { - codegenModel.discriminator = schema + codegenModel.discriminator = innerModel .getDiscriminator(); } if (innerModel.getXml() != null) {