diff --git a/README.md b/README.md index c37f729..623a736 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The client can be used with Java 1.8+ and pulled into Maven or Gradle projects. com.vertexvis api-client-java - 0.16.0 + 0.17.0 compile ``` @@ -25,13 +25,13 @@ The client can be used with Java 1.8+ and pulled into Maven or Gradle projects. ### Gradle ```groovy -compile "com.vertexvis:api-client-java:0.16.0" +compile "com.vertexvis:api-client-java:0.17.0" ``` ### Sbt ```sbt -libraryDependencies += "com.vertexvis" % "api-client-java" % "0.16.0" +libraryDependencies += "com.vertexvis" % "api-client-java" % "0.17.0" ``` ### Others @@ -44,7 +44,7 @@ mvn clean package Then manually install the following JARs. -- `target/api-client-java-0.16.0.jar` +- `target/api-client-java-0.17.0.jar` - `target/lib/*.jar` ## Usage @@ -104,7 +104,7 @@ To consume published snapshot versions in other projects, add the snapshot repos com.vertexvis api-client-java - 0.16.0-SNAPSHOT + 0.17.0-SNAPSHOT ``` @@ -119,7 +119,7 @@ repositories { } dependencies { - implementation 'com.vertexvis:api-client-java:0.16.0-SNAPSHOT' + implementation 'com.vertexvis:api-client-java:0.17.0-SNAPSHOT' } ``` diff --git a/build.gradle b/build.gradle index 7cc1604..51dc9d3 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id "io.github.gradle-nexus.publish-plugin" } -def projectVersion = '0.16.0' +def projectVersion = '0.17.0' def isSnapshot = project.hasProperty('isSnapshot') && project.isSnapshot.toBoolean() version = isSnapshot ? "${projectVersion}-SNAPSHOT" : projectVersion diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index d3ce4e0..98b4e95 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -7,9 +7,16 @@ repositories { mavenCentral() } +def rootProperties = new Properties() +def rootPropertiesFile = file("../gradle.properties") +if (rootPropertiesFile.exists()) { + rootPropertiesFile.withInputStream { rootProperties.load(it) } +} +def openapiGeneratorVersion = rootProperties.getProperty("openapiGeneratorVersion", "7.14.0") + dependencies { - implementation 'org.openapitools:openapi-generator-gradle-plugin:7.14.0' - implementation 'org.openapitools:openapi-generator:7.14.0' + implementation "org.openapitools:openapi-generator-gradle-plugin:${openapiGeneratorVersion}" + implementation "org.openapitools:openapi-generator:${openapiGeneratorVersion}" implementation 'io.swagger.core.v3:swagger-models:2.2.31' implementation 'io.github.gradle-nexus:publish-plugin:2.0.0' } diff --git a/buildSrc/src/main/groovy/vertex.openapi-generator.gradle b/buildSrc/src/main/groovy/vertex.openapi-generator.gradle index 9668f66..750602d 100644 --- a/buildSrc/src/main/groovy/vertex.openapi-generator.gradle +++ b/buildSrc/src/main/groovy/vertex.openapi-generator.gradle @@ -7,6 +7,48 @@ repositories { mavenCentral() } +def vertexOpenapiGeneratorVersion = project.findProperty("openapiGeneratorVersion") ?: "7.14.0" +def templateRootDir = "${buildDir}/openapi-templates" +def templateDirPath = "${templateRootDir}/Java/libraries/okhttp-gson" +def patchDirPath = "${project.rootDir}/openapi-generator-plugin/src/main/resources/patches" + +configurations { + vertexOpenapiGeneratorTemplates +} + +dependencies { + vertexOpenapiGeneratorTemplates("org.openapitools:openapi-generator:${vertexOpenapiGeneratorVersion}") { + transitive = false + } +} + +tasks.register("prepareOpenApiTemplates") { + outputs.dir(templateRootDir) + doLast { + def generatorJar = configurations.vertexOpenapiGeneratorTemplates.singleFile + copy { + from(zipTree(generatorJar)) + include "Java/libraries/okhttp-gson/**" + into templateRootDir + } + def patchDir = file(patchDirPath) + if (!patchDir.exists()) { + throw new GradleException("Patch directory not found at ${patchDir}") + } + + def patches = fileTree(patchDir).matching { include "*.patch" }.files.sort { it.name } + patches.each { patchFile -> + exec { + workingDir = file(templateDirPath) + commandLine "patch", "--batch", "--forward", "--reject-file=-", "-p0", "-i", patchFile.absolutePath + } + } + + def relPath = project.rootDir.toPath().relativize(file(templateDirPath).toPath()).toString() + println "OpenAPI templates prepared at: ${relPath}" + } +} + openApiGenerate { verbose = false generatorName = 'vertex-java' // Use our custom generator @@ -18,7 +60,7 @@ openApiGenerate { invokerPackage = 'com.vertexvis' modelPackage = 'com.vertexvis.model' apiPackage = 'com.vertexvis.api' - templateDir = "${project.rootDir}/buildSrc/src/main/resources/vertex-java" + templateDir = templateDirPath configOptions = [ openApiNullable: "false", dateLibrary: "java8", @@ -46,3 +88,4 @@ sourceSets { // Make sure compilation depends on code generation compileJava.dependsOn tasks.openApiGenerate +tasks.openApiGenerate.dependsOn tasks.prepareOpenApiTemplates diff --git a/buildSrc/src/main/resources/vertex-java/oneof_model.mustache b/buildSrc/src/main/resources/vertex-java/oneof_model.mustache deleted file mode 100644 index 50e03ca..0000000 --- a/buildSrc/src/main/resources/vertex-java/oneof_model.mustache +++ /dev/null @@ -1,537 +0,0 @@ - - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonParseException; -import com.google.gson.TypeAdapter; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.JsonPrimitive; -import com.google.gson.annotations.JsonAdapter; -import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonArray; -import com.google.gson.JsonParseException; - -import {{invokerPackage}}.JSON; - -// This source file was generated using a Vertex modified version of the oneof_model.mustache template. - -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} -public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}} implements {{{.}}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-implements}} { - private static final Logger log = Logger.getLogger({{classname}}.class.getName()); - - public static class CustomTypeAdapterFactory implements TypeAdapterFactory { - @SuppressWarnings("unchecked") - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { - return null; // this class only serializes '{{classname}}' and its subtypes - } - final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); - {{#composedSchemas}} - {{#oneOf}} - {{^isArray}} - {{^isMap}} - {{^vendorExtensions.x-duplicated-data-type}} - final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = gson.getDelegateAdapter(this, TypeToken.get({{{dataType}}}.class)); - {{/vendorExtensions.x-duplicated-data-type}} - {{/isMap}} - {{/isArray}} - {{#isArray}} - - final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType(); - final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}})); - {{/isArray}} - {{#isMap}} - final Type typeInstance{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = new TypeToken<{{{dataType}}}>(){}.getType(); - final TypeAdapter<{{{dataType}}}> adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}} = (TypeAdapter<{{{dataType}}}>) gson.getDelegateAdapter(this, TypeToken.get(typeInstance{{#sanitizeGeneric}}{{{dataType}}}{{/sanitizeGeneric}})); - {{/isMap}} - {{/oneOf}} - {{/composedSchemas}} - - return (TypeAdapter) new TypeAdapter<{{classname}}>() { - @Override - public void write(JsonWriter out, {{classname}} value) throws IOException { - if (value == null || value.getActualInstance() == null) { - elementAdapter.write(out, null); - return; - } - - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type}} - // check if the actual instance is of the type `{{{dataType}}}` - if (value.getActualInstance() instanceof {{#isArray}}List{{/isArray}}{{#isMap}}Map{{/isMap}}{{^isMap}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isMap}}) { - {{#isPrimitiveType}} - {{^isMap}} - JsonPrimitive primitive = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonPrimitive(); - elementAdapter.write(out, primitive); - return; - {{/isMap}} - {{#isMap}} - JsonObject object = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonObject(); - elementAdapter.write(out, object); - return; - {{/isMap}} - {{/isPrimitiveType}} - {{^isPrimitiveType}} - {{#isArray}} - List list = (List) value.getActualInstance(); - if (list.get(0) instanceof {{{items.dataType}}}) { - JsonArray array = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()).getAsJsonArray(); - elementAdapter.write(out, array); - return; - } - {{/isArray}} - {{/isPrimitiveType}} - {{^isMap}} - {{^isArray}} - {{^isPrimitiveType}} - JsonElement element = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.toJsonTree(({{{dataType}}})value.getActualInstance()); - elementAdapter.write(out, element); - return; - {{/isPrimitiveType}} - {{/isArray}} - {{/isMap}} - } - {{/vendorExtensions.x-duplicated-data-type}} - {{/oneOf}} - {{/composedSchemas}} - throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); - } - - @Override - public {{classname}} read(JsonReader in) throws IOException { - Object deserialized = null; - JsonElement jsonElement = elementAdapter.read(in); - - {{#useOneOfDiscriminatorLookup}} - {{#discriminator}} - JsonObject jsonObject = jsonElement.getAsJsonObject(); - - // use discriminator value for faster oneOf lookup - {{classname}} new{{classname}} = new {{classname}}(); - if (jsonObject.get("{{{propertyBaseName}}}") == null) { - log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty."); - } else { - // look up the discriminator value in the field `{{{propertyBaseName}}}` - switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) { - {{#mappedModels}} - case "{{{mappingName}}}": - deserialized = adapter{{modelName}}.fromJsonTree(jsonObject); - new{{classname}}.setActualInstance(deserialized); - return new{{classname}}; - {{/mappedModels}} - default: - log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString())); - } - } - - {{/discriminator}} - {{/useOneOfDiscriminatorLookup}} - int match = 0; - ArrayList errorMessages = new ArrayList<>(); - TypeAdapter actualAdapter = elementAdapter; - - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type}} - {{^hasVars}} - // deserialize {{{dataType}}} - try { - // validate the JSON object to see if any exception is thrown - {{^isArray}} - {{^isMap}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}; - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}; - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(jsonElement); - actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}; - {{/isPrimitiveType}} - {{/isNumber}} - {{/isMap}} - {{/isArray}} - {{#isArray}} - if (!jsonElement.isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString())); - } - - JsonArray array = jsonElement.getAsJsonArray(); - // validate array items - for(JsonElement element : array) { - {{#items}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element); - {{/isPrimitiveType}} - {{/isNumber}} - {{/items}} - } - actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}; - {{/isArray}} - {{#isMap}} - if (!jsonElement.isJsonObject()) { - throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString())); - } - - {{^isFreeFormObject}} - Map map = jsonElement.getAsJsonObject().asMap(); - // validate map items - for(JsonElement element : map.values()) { - {{#items}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element); - {{/isPrimitiveType}} - {{/isNumber}} - {{/items}} - } - {{/isFreeFormObject}} - actualAdapter = adapter{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}; - {{/isMap}} - match++; - log.log(Level.FINER, "Input data matches schema '{{{dataType}}}'"); - } catch (Exception e) { - // deserialization failed, continue - errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage())); - log.log(Level.FINER, "Input data does not match schema '{{{dataType}}}'", e); - } - {{/hasVars}} - {{#hasVars}} - // deserialize {{{.}}} - try { - // validate the JSON object to see if any exception is thrown - {{.}}.validateJsonElement(jsonElement); - actualAdapter = adapter{{.}}; - match++; - log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); - } catch (Exception e) { - // deserialization failed, continue - errorMessages.add(String.format("Deserialization for {{{.}}} failed with `%s`.", e.getMessage())); - log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); - } - {{/hasVars}} - {{/vendorExtensions.x-duplicated-data-type}} - {{/oneOf}} - {{/composedSchemas}} - - if (match == 1) { - {{classname}} ret = new {{classname}}(); - ret.setActualInstance(actualAdapter.fromJsonTree(jsonElement)); - return ret; - } - - throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonElement.toString())); - } - }.nullSafe(); - } - } - - // store a list of schema names defined in oneOf - public static final Map> schemas = new HashMap>(); - - public {{classname}}() { - super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); - } - - public {{classname}}(Object o) { - super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); - setActualInstance(o); - } - - static { - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type}} - schemas.put("{{{dataType}}}", {{{baseType}}}.class); - {{/vendorExtensions.x-duplicated-data-type}} - {{/oneOf}} - {{/composedSchemas}} - } - - @Override - public Map> getSchemas() { - return {{classname}}.schemas; - } - - /** - * Set the instance that matches the oneOf child schema, check - * the instance parameter is valid against the oneOf child schemas: - * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} - * - * It could be an instance of the 'oneOf' schemas. - */ - @Override - public void setActualInstance(Object instance) { - {{#isNullable}} - if (instance == null) { - super.setActualInstance(instance); - return; - } - - {{/isNullable}} - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type}} - if (instance instanceof {{#isArray}}List{{/isArray}}{{#isMap}}Map{{/isMap}}{{^isMap}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isMap}}) { - {{#isArray}} - List list = (List) instance; - if (list.get(0) instanceof {{{items.dataType}}}) { - super.setActualInstance(instance); - return; - } - {{/isArray}} - {{^isArray}} - super.setActualInstance(instance); - return; - {{/isArray}} - } - - {{/vendorExtensions.x-duplicated-data-type}} - {{/oneOf}} - {{/composedSchemas}} - throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); - } - - /** - * Get the actual instance, which can be the following: - * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} - * - * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) - */ - @SuppressWarnings("unchecked") - @Override - public Object getActualInstance() { - return super.getActualInstance(); - } - - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type-ignoring-erasure}} - /** - * Get the actual instance of `{{{dataType}}}`. If the actual instance is not `{{{dataType}}}`, - * the ClassCastException will be thrown. - * - * @return The actual instance of `{{{dataType}}}` - * @throws ClassCastException if the instance is not `{{{dataType}}}` - */ - public {{{dataType}}} get{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}() throws ClassCastException { - return ({{{dataType}}})super.getActualInstance(); - } - - {{/vendorExtensions.x-duplicated-data-type-ignoring-erasure}} - {{/oneOf}} - {{/composedSchemas}} - /** - * Validates the JSON Element and throws an exception if issues found - * - * @param jsonElement JSON Element - * @throws IOException if the JSON Element is invalid with respect to {{classname}} - */ - public static void validateJsonElement(JsonElement jsonElement) throws IOException { - {{#useOneOfDiscriminatorLookup}} - {{#discriminator}} - // Vertex customization -- use the same behavior as the read method. - JsonObject jsonObject = jsonElement != null ? jsonElement.getAsJsonObject() : null; - - if (jsonObject != null) { - if (jsonObject.get("type") == null) { - log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty."); - } else { - // look up the discriminator value in the field `{{{propertyBaseName}}}` - switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) { - {{#mappedModels}} - case "{{{mappingName}}}": - {{modelName}}.validateJsonElement(jsonElement); - return; - {{/mappedModels}} - default: - log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString())); - } - } - } - {{/discriminator}} - {{/useOneOfDiscriminatorLookup}} - // validate oneOf schemas one by one - int validCount = 0; - ArrayList errorMessages = new ArrayList<>(); - {{#composedSchemas}} - {{#oneOf}} - {{^vendorExtensions.x-duplicated-data-type}} - // validate the json string with {{{dataType}}} - try { - {{^hasVars}} - {{^isMap}} - {{^isArray}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!jsonElement.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(jsonElement); - {{/isPrimitiveType}} - {{/isNumber}} - {{/isArray}} - {{/isMap}} - {{#isArray}} - if (!jsonElement.isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected json element to be a array type in the JSON string but got `%s`", jsonElement.toString())); - } - JsonArray array = jsonElement.getAsJsonArray(); - // validate array items - for(JsonElement element : array) { - {{#items}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element); - {{/isPrimitiveType}} - {{/isNumber}} - {{/items}} - } - {{/isArray}} - {{#isMap}} - if (!jsonElement.isJsonObject()) { - throw new IllegalArgumentException(String.format("Expected json element to be a object type in the JSON string but got `%s`", jsonElement.toString())); - } - - {{^isFreeFormObject}} - Map map = jsonElement.getAsJsonObject().asMap(); - // validate map items - for(JsonElement element : map.values()) { - {{#items}} - {{#isNumber}} - if (!jsonElement.getAsJsonPrimitive().isNumber()) { - throw new IllegalArgumentException(String.format("Expected json element to be of type Number in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isNumber}} - {{^isNumber}} - {{#isPrimitiveType}} - if (!element.getAsJsonPrimitive().is{{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}}()) { - throw new IllegalArgumentException(String.format("Expected array items to be of type {{#isBoolean}}Boolean{{/isBoolean}}{{#isString}}String{{/isString}}{{^isString}}{{^isBoolean}}Number{{/isBoolean}}{{/isString}} in the JSON string but got `%s`", jsonElement.toString())); - } - {{/isPrimitiveType}} - {{/isNumber}} - {{^isNumber}} - {{^isPrimitiveType}} - {{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}.validateJsonElement(element); - {{/isPrimitiveType}} - {{/isNumber}} - {{/items}} - } - {{/isFreeFormObject}} - {{/isMap}} - {{/hasVars}} - {{#hasVars}} - {{{.}}}.validateJsonElement(jsonElement); - validCount++; - {{/hasVars}} - validCount++; - } catch (Exception e) { - errorMessages.add(String.format("Deserialization for {{{dataType}}} failed with `%s`.", e.getMessage())); - // continue to the next one - } - {{/vendorExtensions.x-duplicated-data-type}} - {{/oneOf}} - {{/composedSchemas}} - if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for {{classname}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString())); - } - } - - /** - * Create an instance of {{classname}} given an JSON string - * - * @param jsonString JSON string - * @return An instance of {{classname}} - * @throws IOException if the JSON string is invalid with respect to {{classname}} - */ - public static {{{classname}}} fromJson(String jsonString) throws IOException { - return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); - } - - /** - * Convert an instance of {{classname}} to an JSON string - * - * @return JSON string - */ - public String toJson() { - return JSON.getGson().toJson(this); - } -} diff --git a/buildSrc/src/main/resources/vertex-java/pojo.mustache b/buildSrc/src/main/resources/vertex-java/pojo.mustache deleted file mode 100644 index af2ed13..0000000 --- a/buildSrc/src/main/resources/vertex-java/pojo.mustache +++ /dev/null @@ -1,602 +0,0 @@ -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import java.io.IOException; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import {{invokerPackage}}.JSON; - -// This source file was generated using a Vertex modified version of the pojo.mustache template. - -/** - * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} - * @deprecated{{/isDeprecated}} - */{{#isDeprecated}} -@Deprecated{{/isDeprecated}} -{{#swagger1AnnotationLibrary}} -{{#description}} -@ApiModel(description = "{{{.}}}") -{{/description}} -{{/swagger1AnnotationLibrary}} -{{#swagger2AnnotationLibrary}} -{{#description}} -@Schema(description = "{{{.}}}") -{{/description}} -{{/swagger2AnnotationLibrary}} -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -{{#vendorExtensions.x-class-extra-annotation}} -{{{vendorExtensions.x-class-extra-annotation}}} -{{/vendorExtensions.x-class-extra-annotation}} -public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ -{{#serializableModel}} - private static final long serialVersionUID = 1L; - -{{/serializableModel}} - {{#vars}} - {{#isEnum}} - {{^isContainer}} -{{>modelInnerEnum}} - - {{/isContainer}} - {{#isContainer}} - {{#mostInnerItems}} -{{>modelInnerEnum}} - - {{/mostInnerItems}} - {{/isContainer}} - {{/isEnum}} - public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; - {{#withXml}} - @Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}}) - {{#isXmlWrapped}} - @XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}}) - {{/isXmlWrapped}} - {{/withXml}} - {{#deprecated}} - @Deprecated - {{/deprecated}} - @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) - {{#vendorExtensions.x-field-extra-annotation}} - {{{vendorExtensions.x-field-extra-annotation}}} - {{/vendorExtensions.x-field-extra-annotation}} - {{>nullable_var_annotations}}{{! prevent indent}} - {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; - - {{/vars}} - public {{classname}}() { - {{#parent}} - {{#parcelableModel}} - super(); - {{/parcelableModel}} - {{/parent}} - {{#discriminator}} - {{#discriminator.isEnum}} -{{#readWriteVars}}{{#isDiscriminator}}{{#defaultValue}} - this.{{name}} = {{defaultValue}}; -{{/defaultValue}}{{/isDiscriminator}}{{/readWriteVars}} - {{/discriminator.isEnum}} - {{^discriminator.isEnum}} - this.{{{discriminatorName}}} = this.getClass().getSimpleName(); - {{/discriminator.isEnum}} - {{/discriminator}} - } - {{#vendorExtensions.x-has-readonly-properties}} - {{^withXml}} - - public {{classname}}( - {{#readOnlyVars}} - {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} - {{/readOnlyVars}} - ) { - this(); - {{#readOnlyVars}} - this.{{name}} = {{name}}; - {{/readOnlyVars}} - } - {{/withXml}} - {{/vendorExtensions.x-has-readonly-properties}} - {{#vars}} - - {{^isReadOnly}} - {{#deprecated}} - @Deprecated - {{/deprecated}} - public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; - return this; - } - {{#isArray}} - - public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}; - } - this.{{name}}.add({{name}}Item); - return this; - } - {{/isArray}} - {{#isMap}} - - public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}; - } - this.{{name}}.put(key, {{name}}Item); - return this; - } - {{/isMap}} - - {{/isReadOnly}} - /** - {{#description}} - * {{.}} - {{/description}} - {{^description}} - * Get {{name}} - {{/description}} - {{#minimum}} - * minimum: {{.}} - {{/minimum}} - {{#maximum}} - * maximum: {{.}} - {{/maximum}} - * @return {{name}} - {{#deprecated}} - * @deprecated - {{/deprecated}} - */ -{{#deprecated}} - @Deprecated -{{/deprecated}} - {{>nullable_var_annotations}}{{! prevent indent}} -{{#useBeanValidation}} -{{>beanValidation}} - -{{/useBeanValidation}} -{{#swagger1AnnotationLibrary}} - @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") -{{/swagger1AnnotationLibrary}} -{{#swagger2AnnotationLibrary}} - @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}") -{{/swagger2AnnotationLibrary}} -{{#vendorExtensions.x-extra-annotation}} - {{{vendorExtensions.x-extra-annotation}}} -{{/vendorExtensions.x-extra-annotation}} - public {{{datatypeWithEnum}}} {{getter}}() { - return {{name}}; - } - - {{^isReadOnly}} -{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} -{{/vendorExtensions.x-setter-extra-annotation}}{{#deprecated}} @Deprecated -{{/deprecated}} public void {{setter}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; - } - {{/isReadOnly}} - - {{/vars}} -{{>libraries/okhttp-gson/additional_properties}} - - - @Override - public boolean equals(Object o) { - {{#useReflectionEqualsHashCode}} - return EqualsBuilder.reflectionEquals(this, o, false, null, true); - {{/useReflectionEqualsHashCode}} - {{^useReflectionEqualsHashCode}} - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && - {{/-last}}{{/vars}}{{#isAdditionalPropertiesTrue}}&& - Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/isAdditionalPropertiesTrue}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} - {{/useReflectionEqualsHashCode}} - }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} - - private static boolean equalsNullable(JsonNullable a, JsonNullable b) { - return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); - }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} - - @Override - public int hashCode() { - {{#useReflectionEqualsHashCode}} - return HashCodeBuilder.reflectionHashCode(this); - {{/useReflectionEqualsHashCode}} - {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#isAdditionalPropertiesTrue}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/isAdditionalPropertiesTrue}}); - {{/useReflectionEqualsHashCode}} - }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} - - private static int hashCodeNullable(JsonNullable a) { - if (a == null) { - return 1; - } - return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; - }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class {{classname}} {\n"); - {{#parent}} - sb.append(" ").append(toIndentedString(super.toString())).append("\n"); - {{/parent}} - {{#vars}} - sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n"); - {{/vars}} -{{#isAdditionalPropertiesTrue}} - sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); -{{/isAdditionalPropertiesTrue}} - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - -{{#parcelableModel}} - - public void writeToParcel(Parcel out, int flags) { -{{#model}} -{{#isArray}} - out.writeList(this); -{{/isArray}} -{{^isArray}} -{{#parent}} - super.writeToParcel(out, flags); -{{/parent}} -{{#vars}} - out.writeValue({{name}}); -{{/vars}} -{{/isArray}} -{{/model}} - } - - {{classname}}(Parcel in) { -{{#isArray}} - in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArray}} -{{^isArray}} -{{#parent}} - super(in); -{{/parent}} -{{#vars}} -{{#isPrimitiveType}} - {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); -{{/isPrimitiveType}} -{{^isPrimitiveType}} - {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); -{{/isPrimitiveType}} -{{/vars}} -{{/isArray}} - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { - public {{classname}} createFromParcel(Parcel in) { -{{#model}} -{{#isArray}} - {{classname}} result = new {{classname}}(); - result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); - return result; -{{/isArray}} -{{^isArray}} - return new {{classname}}(in); -{{/isArray}} -{{/model}} - } - public {{classname}}[] newArray(int size) { - return new {{classname}}[size]; - } - }; -{{/parcelableModel}} - - public static HashSet openapiFields; - public static HashSet openapiRequiredFields; - - static { - // a set of all properties/fields (JSON key names) - {{#hasVars}} - openapiFields = new HashSet(Arrays.asList({{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}})); - {{/hasVars}} - {{^hasVars}} - openapiFields = new HashSet(0); - {{/hasVars}} - - // a set of required properties/fields (JSON key names) - {{#hasRequired}} - openapiRequiredFields = new HashSet(Arrays.asList({{#requiredVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/requiredVars}})); - {{/hasRequired}} - {{^hasRequired}} - openapiRequiredFields = new HashSet(0); - {{/hasRequired}} - } - - /** - * Validates the JSON Element and throws an exception if issues found - * - * @param jsonElement JSON Element - * @throws IOException if the JSON Element is invalid with respect to {{classname}} - */ - public static void validateJsonElement(JsonElement jsonElement) throws IOException { - if (jsonElement == null) { - if (!{{classname}}.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null - throw new IllegalArgumentException(String.format("The required field(s) %s in {{{classname}}} is not found in the empty JSON string", {{classname}}.openapiRequiredFields.toString())); - } - } - {{^hasChildren}} - {{^isAdditionalPropertiesTrue}} - Set> entries = jsonElement.getAsJsonObject().entrySet(); - // check to see if the JSON string contains additional fields - for (Map.Entry entry : entries) { - if (!{{classname}}.openapiFields.contains(entry.getKey())) { - throw new IllegalArgumentException(String.format("The field `%s` in the JSON string is not defined in the `{{classname}}` properties. JSON: %s", entry.getKey(), jsonElement.toString())); - } - } - {{/isAdditionalPropertiesTrue}} - {{#requiredVars}} - {{#-first}} - - // check to make sure all required properties/fields are present in the JSON string - for (String requiredField : {{classname}}.openapiRequiredFields) { - if (jsonElement.getAsJsonObject().get(requiredField) == null) { - throw new IllegalArgumentException(String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())); - } - } - {{/-first}} - {{/requiredVars}} - {{/hasChildren}} - {{^discriminator}} - {{#hasVars}} - JsonObject jsonObj = jsonElement.getAsJsonObject(); - {{/hasVars}} - {{#vars}} - {{#isArray}} - {{#items.isModel}} - {{#required}} - // ensure the json data is an array - if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - - JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); - // validate the required field `{{{baseName}}}` (array) - for (int i = 0; i < jsonArray{{name}}.size(); i++) { - {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i)); - }; - {{/required}} - {{^required}} - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); - if (jsonArray{{name}} != null) { - // ensure the json data is an array - if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - - // validate the optional field `{{{baseName}}}` (array) - for (int i = 0; i < jsonArray{{name}}.size(); i++) { - {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i)); - }; - } - } - {{/required}} - {{/items.isModel}} - {{^items.isModel}} - {{^required}} - // ensure the optional json data is an array if present - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull() && !jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/required}} - {{#required}} - // ensure the required json array is present - if (jsonObj.get("{{{baseName}}}") == null) { - throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`"); - } else if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/required}} - {{/items.isModel}} - {{/isArray}} - {{^isContainer}} - {{#isString}} - if ({{#notRequiredOrIsNullable}}(jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) && {{/notRequiredOrIsNullable}}!jsonObj.get("{{{baseName}}}").isJsonPrimitive()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/isString}} - {{#isModel}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isModel}} - {{#isEnum}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isEnum}} - {{#isEnumRef}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isEnumRef}} - {{/isContainer}} - {{/vars}} - {{/discriminator}} - {{#hasChildren}} - {{#discriminator}} - - String discriminatorValue = jsonElement.getAsJsonObject().get("{{{propertyBaseName}}}").getAsString(); - switch (discriminatorValue) { - {{#mappedModels}} - case "{{mappingName}}": - {{modelName}}.validateJsonElement(jsonElement); - break; - {{/mappedModels}} - default: - throw new IllegalArgumentException(String.format("The value of the `{{{propertyBaseName}}}` field `%s` does not match any key defined in the discriminator's mapping.", discriminatorValue)); - } - {{/discriminator}} - {{/hasChildren}} - } - -{{^hasChildren}} - public static class CustomTypeAdapterFactory implements TypeAdapterFactory { - @SuppressWarnings("unchecked") - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { - return null; // this class only serializes '{{classname}}' and its subtypes - } - final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); - final TypeAdapter<{{classname}}> thisAdapter - = gson.getDelegateAdapter(this, TypeToken.get({{classname}}.class)); - - return (TypeAdapter) new TypeAdapter<{{classname}}>() { - @Override - public void write(JsonWriter out, {{classname}} value) throws IOException { - JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); - {{#isAdditionalPropertiesTrue}} - obj.remove("additionalProperties"); - // serialize additional properties - if (value.getAdditionalProperties() != null) { - for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { - if (entry.getValue() instanceof String) - obj.addProperty(entry.getKey(), (String) entry.getValue()); - else if (entry.getValue() instanceof Number) - obj.addProperty(entry.getKey(), (Number) entry.getValue()); - else if (entry.getValue() instanceof Boolean) - obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); - else if (entry.getValue() instanceof Character) - obj.addProperty(entry.getKey(), (Character) entry.getValue()); - else { - JsonElement jsonElement = gson.toJsonTree(entry.getValue()); - if (jsonElement.isJsonArray()) { - obj.add(entry.getKey(), jsonElement.getAsJsonArray()); - } else { - obj.add(entry.getKey(), jsonElement.getAsJsonObject()); - } - } - } - } - {{/isAdditionalPropertiesTrue}} - elementAdapter.write(out, obj); - } - - @Override - public {{classname}} read(JsonReader in) throws IOException { - JsonElement jsonElement = elementAdapter.read(in); -{{^vendorExtensions.x-skip-validation}} - validateJsonElement(jsonElement); -{{/vendorExtensions.x-skip-validation}} -{{#vendorExtensions.x-skip-validation}} - // vertex:TODO: Skipping validation during deserialization of the JSON element based on configuration - // validateJsonElement(jsonElement); -{{/vendorExtensions.x-skip-validation}} - {{#isAdditionalPropertiesTrue}} - JsonObject jsonObj = jsonElement.getAsJsonObject(); - // store additional fields in the deserialized instance - {{classname}} instance = thisAdapter.fromJsonTree(jsonObj); - for (Map.Entry entry : jsonObj.entrySet()) { - if (!openapiFields.contains(entry.getKey())) { - if (entry.getValue().isJsonPrimitive()) { // primitive type - if (entry.getValue().getAsJsonPrimitive().isString()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); - else if (entry.getValue().getAsJsonPrimitive().isNumber()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); - else if (entry.getValue().getAsJsonPrimitive().isBoolean()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); - else - throw new IllegalArgumentException(String.format("The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); - } else if (entry.getValue().isJsonArray()) { - instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); - } else { // JSON object - instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); - } - } - } - return instance; - {{/isAdditionalPropertiesTrue}} - {{^isAdditionalPropertiesTrue}} - return thisAdapter.fromJsonTree(jsonElement); - {{/isAdditionalPropertiesTrue}} - } - - }.nullSafe(); - } - } -{{/hasChildren}} - - /** - * Create an instance of {{classname}} given an JSON string - * - * @param jsonString JSON string - * @return An instance of {{classname}} - * @throws IOException if the JSON string is invalid with respect to {{classname}} - */ - public static {{{classname}}} fromJson(String jsonString) throws IOException { - return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); - } - - /** - * Convert an instance of {{classname}} to an JSON string - * - * @return JSON string - */ - public String toJson() { - return JSON.getGson().toJson(this); - } -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3e273f3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +openapiGeneratorVersion=7.14.0 diff --git a/openapi-generator-plugin/src/main/resources/patches/ApiClient.mustache.patch b/openapi-generator-plugin/src/main/resources/patches/ApiClient.mustache.patch new file mode 100644 index 0000000..ac736c4 --- /dev/null +++ b/openapi-generator-plugin/src/main/resources/patches/ApiClient.mustache.patch @@ -0,0 +1,70 @@ +--- ApiClient.mustache ++++ ApiClient.mustache +@@ -37,6 +37,8 @@ + import java.net.URI; + import java.net.URLConnection; + import java.net.URLEncoder; ++import java.nio.charset.Charset; ++import java.nio.charset.StandardCharsets; + import java.nio.file.Files; + import java.nio.file.Paths; + import java.security.GeneralSecurityException; +@@ -1922,17 +1924,48 @@ + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object into a string + */ + protected String requestBodyToString(RequestBody requestBody) throws ApiException { +- if (requestBody != null) { +- try { +- final Buffer buffer = new Buffer(); +- requestBody.writeTo(buffer); +- return buffer.readUtf8(); +- } catch (final IOException e) { +- throw new ApiException(e); +- } ++ // Payload is only used by some auth schemes; for large/binary uploads we must not buffer. ++ if (requestBody == null) { ++ return ""; + } + +- // empty http request body +- return ""; ++ // If you *know* none of your auth implementations use payload, you can simply: ++ // return ""; ++ ++ // Otherwise, keep a safe, capped implementation: ++ try { ++ final MediaType contentType = requestBody.contentType(); ++ final long maxBytes = 64L * 1024L; // 64KiB cap ++ ++ // Do not attempt to stringify binary bodies. ++ if (contentType != null) { ++ final String type = contentType.type(); ++ final String subtype = contentType.subtype(); ++ final boolean textLike = ++ "text".equalsIgnoreCase(type) || ++ (subtype != null && ( ++ subtype.toLowerCase().contains("json") || ++ subtype.toLowerCase().contains("xml") || ++ subtype.toLowerCase().contains("x-www-form-urlencoded") ++ )); ++ if (!textLike) return ""; ++ } ++ ++ final long declaredLength = requestBody.contentLength(); ++ if (declaredLength > maxBytes) { ++ return ""; ++ } ++ ++ final Buffer buffer = new Buffer(); ++ requestBody.writeTo(buffer); ++ ++ final long toRead = Math.min(buffer.size(), maxBytes); ++ final Charset charset = ++ (contentType != null && contentType.charset() != null) ? contentType.charset() : StandardCharsets.UTF_8; ++ ++ return buffer.readString(toRead, charset); ++ } catch (final IOException e) { ++ throw new ApiException(e); ++ } + } + } diff --git a/openapi-generator-plugin/src/main/resources/patches/oneof_model.mustache.patch b/openapi-generator-plugin/src/main/resources/patches/oneof_model.mustache.patch new file mode 100644 index 0000000..73825dd --- /dev/null +++ b/openapi-generator-plugin/src/main/resources/patches/oneof_model.mustache.patch @@ -0,0 +1,41 @@ +--- oneof_model.mustache ++++ oneof_model.mustache +@@ -33,6 +33,8 @@ + + import {{invokerPackage}}.JSON; + ++// This source file was generated using a Vertex modified version of the oneof_model.mustache template. ++ + {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} + public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}} implements {{{.}}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); +@@ -383,6 +385,29 @@ + * @throws IOException if the JSON Element is invalid with respect to {{classname}} + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { ++ {{#useOneOfDiscriminatorLookup}} ++ {{#discriminator}} ++ // Vertex customization -- use the same behavior as the read method. ++ JsonObject jsonObject = jsonElement != null ? jsonElement.getAsJsonObject() : null; ++ ++ if (jsonObject != null) { ++ if (jsonObject.get("type") == null) { ++ log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty."); ++ } else { ++ // look up the discriminator value in the field `{{{propertyBaseName}}}` ++ switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) { ++ {{#mappedModels}} ++ case "{{{mappingName}}}": ++ {{modelName}}.validateJsonElement(jsonElement); ++ return; ++ {{/mappedModels}} ++ default: ++ log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString())); ++ } ++ } ++ } ++ {{/discriminator}} ++ {{/useOneOfDiscriminatorLookup}} + // validate oneOf schemas one by one + int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); diff --git a/openapi-generator-plugin/src/main/resources/patches/pojo.mustache.patch b/openapi-generator-plugin/src/main/resources/patches/pojo.mustache.patch new file mode 100644 index 0000000..1f08cfc --- /dev/null +++ b/openapi-generator-plugin/src/main/resources/patches/pojo.mustache.patch @@ -0,0 +1,89 @@ +--- pojo.mustache ++++ pojo.mustache +@@ -21,6 +21,8 @@ + + import {{invokerPackage}}.JSON; + ++// This source file was generated using a Vertex modified version of the pojo.mustache template. ++ + /** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} +\ No newline at end of file +@@ -49,10 +51,12 @@ + {{#isEnum}} + {{^isContainer}} + {{>modelInnerEnum}} ++ + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} + {{>modelInnerEnum}} ++ + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} +\ No newline at end of file +@@ -70,7 +74,7 @@ + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} +- {{>nullable_var_annotations}} ++ {{>nullable_var_annotations}}{{! prevent indent}} + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + + {{/vars}} +\ No newline at end of file +@@ -159,9 +163,10 @@ + {{#deprecated}} + @Deprecated + {{/deprecated}} +- {{>nullable_var_annotations}} ++ {{>nullable_var_annotations}}{{! prevent indent}} + {{#useBeanValidation}} + {{>beanValidation}} ++ + {{/useBeanValidation}} + {{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +\ No newline at end of file +@@ -187,6 +192,7 @@ + {{/vars}} + {{>libraries/okhttp-gson/additional_properties}} + ++ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} +\ No newline at end of file +@@ -352,7 +358,6 @@ + } + {{^hasChildren}} + {{^isAdditionalPropertiesTrue}} +- + Set> entries = jsonElement.getAsJsonObject().entrySet(); + // check to see if the JSON string contains additional fields + for (Map.Entry entry : entries) { +\ No newline at end of file +@@ -534,7 +539,13 @@ + @Override + public {{classname}} read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); ++{{^vendorExtensions.x-skip-validation}} + validateJsonElement(jsonElement); ++{{/vendorExtensions.x-skip-validation}} ++{{#vendorExtensions.x-skip-validation}} ++ // vertex:TODO: Skipping validation during deserialization of the JSON element based on configuration ++ // validateJsonElement(jsonElement); ++{{/vendorExtensions.x-skip-validation}} + {{#isAdditionalPropertiesTrue}} + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance +\ No newline at end of file +@@ -588,4 +599,4 @@ + public String toJson() { + return JSON.getGson().toJson(this); + } +-} ++} +\ No newline at end of file diff --git a/openapi-generator-plugin/src/main/resources/vertex-java/pojo.mustache b/openapi-generator-plugin/src/main/resources/vertex-java/pojo.mustache deleted file mode 100644 index e1f16c3..0000000 --- a/openapi-generator-plugin/src/main/resources/vertex-java/pojo.mustache +++ /dev/null @@ -1,601 +0,0 @@ -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.TypeAdapterFactory; -import com.google.gson.reflect.TypeToken; -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import java.io.IOException; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import {{invokerPackage}}.JSON; - -/** - * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} - * @deprecated{{/isDeprecated}} - */{{#isDeprecated}} -@Deprecated{{/isDeprecated}} -{{#swagger1AnnotationLibrary}} -{{#description}} -@ApiModel(description = "{{{.}}}") -{{/description}} -{{/swagger1AnnotationLibrary}} -{{#swagger2AnnotationLibrary}} -{{#description}} -@Schema(description = "{{{.}}}") -{{/description}} -{{/swagger2AnnotationLibrary}} -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -{{#vendorExtensions.x-class-extra-annotation}} -{{{vendorExtensions.x-class-extra-annotation}}} -{{/vendorExtensions.x-class-extra-annotation}} -public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ -{{#serializableModel}} - private static final long serialVersionUID = 1L; - -{{/serializableModel}} - {{#vars}} - {{#isEnum}} - {{^isContainer}} -{{>modelInnerEnum}} - - {{/isContainer}} - {{#isContainer}} - {{#mostInnerItems}} -{{>modelInnerEnum}} - - {{/mostInnerItems}} - {{/isContainer}} - {{/isEnum}} - public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; - {{#withXml}} - @Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}}) - {{#isXmlWrapped}} - @XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}}) - {{/isXmlWrapped}} - {{/withXml}} - {{#deprecated}} - @Deprecated - {{/deprecated}} - @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) - {{#vendorExtensions.x-field-extra-annotation}} - {{{vendorExtensions.x-field-extra-annotation}}} - {{/vendorExtensions.x-field-extra-annotation}} - {{>nullable_var_annotations}}{{! prevent indent}} - {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; - - {{/vars}} - public {{classname}}() { - {{#parent}} - {{#parcelableModel}} - super(); - {{/parcelableModel}} - {{/parent}} - {{#discriminator}} - {{#discriminator.isEnum}} -{{#readWriteVars}}{{#isDiscriminator}}{{#defaultValue}} - this.{{name}} = {{defaultValue}}; -{{/defaultValue}}{{/isDiscriminator}}{{/readWriteVars}} - {{/discriminator.isEnum}} - {{^discriminator.isEnum}} - this.{{{discriminatorName}}} = this.getClass().getSimpleName(); - {{/discriminator.isEnum}} - {{/discriminator}} - } - {{#vendorExtensions.x-has-readonly-properties}} - {{^withXml}} - - public {{classname}}( - {{#readOnlyVars}} - {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} - {{/readOnlyVars}} - ) { - this(); - {{#readOnlyVars}} - this.{{name}} = {{name}}; - {{/readOnlyVars}} - } - {{/withXml}} - {{/vendorExtensions.x-has-readonly-properties}} - {{#vars}} - - {{^isReadOnly}} - {{#deprecated}} - @Deprecated - {{/deprecated}} - public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; - return this; - } - {{#isArray}} - - public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}; - } - this.{{name}}.add({{name}}Item); - return this; - } - {{/isArray}} - {{#isMap}} - - public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}; - } - this.{{name}}.put(key, {{name}}Item); - return this; - } - {{/isMap}} - - {{/isReadOnly}} - /** - {{#description}} - * {{.}} - {{/description}} - {{^description}} - * Get {{name}} - {{/description}} - {{#minimum}} - * minimum: {{.}} - {{/minimum}} - {{#maximum}} - * maximum: {{.}} - {{/maximum}} - * @return {{name}} - {{#deprecated}} - * @deprecated - {{/deprecated}} - */ -{{#deprecated}} - @Deprecated -{{/deprecated}} - {{>nullable_var_annotations}}{{! prevent indent}} -{{#useBeanValidation}} -{{>beanValidation}} - -{{/useBeanValidation}} -{{#swagger1AnnotationLibrary}} - @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") -{{/swagger1AnnotationLibrary}} -{{#swagger2AnnotationLibrary}} - @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}") -{{/swagger2AnnotationLibrary}} -{{#vendorExtensions.x-extra-annotation}} - {{{vendorExtensions.x-extra-annotation}}} -{{/vendorExtensions.x-extra-annotation}} - public {{{datatypeWithEnum}}} {{getter}}() { - return {{name}}; - } - - {{^isReadOnly}} -{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} -{{/vendorExtensions.x-setter-extra-annotation}}{{#deprecated}} @Deprecated -{{/deprecated}} public void {{setter}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) { - this.{{name}} = {{name}}; - } - {{/isReadOnly}} - - {{/vars}} -{{>libraries/okhttp-gson/additional_properties}} - - - @Override - public boolean equals(Object o) { - {{#useReflectionEqualsHashCode}} - return EqualsBuilder.reflectionEquals(this, o, false, null, true); - {{/useReflectionEqualsHashCode}} - {{^useReflectionEqualsHashCode}} - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} && - {{/-last}}{{/vars}}{{#isAdditionalPropertiesTrue}}&& - Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/isAdditionalPropertiesTrue}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} - {{/useReflectionEqualsHashCode}} - }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} - - private static boolean equalsNullable(JsonNullable a, JsonNullable b) { - return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); - }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} - - @Override - public int hashCode() { - {{#useReflectionEqualsHashCode}} - return HashCodeBuilder.reflectionHashCode(this); - {{/useReflectionEqualsHashCode}} - {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#isAdditionalPropertiesTrue}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/isAdditionalPropertiesTrue}}); - {{/useReflectionEqualsHashCode}} - }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} - - private static int hashCodeNullable(JsonNullable a) { - if (a == null) { - return 1; - } - return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; - }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class {{classname}} {\n"); - {{#parent}} - sb.append(" ").append(toIndentedString(super.toString())).append("\n"); - {{/parent}} - {{#vars}} - sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n"); - {{/vars}} -{{#isAdditionalPropertiesTrue}} - sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); -{{/isAdditionalPropertiesTrue}} - sb.append("}"); - return sb.toString(); - } - - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); - } - -{{#parcelableModel}} - - public void writeToParcel(Parcel out, int flags) { -{{#model}} -{{#isArray}} - out.writeList(this); -{{/isArray}} -{{^isArray}} -{{#parent}} - super.writeToParcel(out, flags); -{{/parent}} -{{#vars}} - out.writeValue({{name}}); -{{/vars}} -{{/isArray}} -{{/model}} - } - - {{classname}}(Parcel in) { -{{#isArray}} - in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArray}} -{{^isArray}} -{{#parent}} - super(in); -{{/parent}} -{{#vars}} -{{#isPrimitiveType}} - {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); -{{/isPrimitiveType}} -{{^isPrimitiveType}} - {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); -{{/isPrimitiveType}} -{{/vars}} -{{/isArray}} - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { - public {{classname}} createFromParcel(Parcel in) { -{{#model}} -{{#isArray}} - {{classname}} result = new {{classname}}(); - result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); - return result; -{{/isArray}} -{{^isArray}} - return new {{classname}}(in); -{{/isArray}} -{{/model}} - } - public {{classname}}[] newArray(int size) { - return new {{classname}}[size]; - } - }; -{{/parcelableModel}} - - public static HashSet openapiFields; - public static HashSet openapiRequiredFields; - - static { - // a set of all properties/fields (JSON key names) - {{#hasVars}} - openapiFields = new HashSet(Arrays.asList({{#allVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/allVars}})); - {{/hasVars}} - {{^hasVars}} - openapiFields = new HashSet(0); - {{/hasVars}} - - // a set of required properties/fields (JSON key names) - {{#hasRequired}} - openapiRequiredFields = new HashSet(Arrays.asList({{#requiredVars}}"{{baseName}}"{{^-last}}, {{/-last}}{{/requiredVars}})); - {{/hasRequired}} - {{^hasRequired}} - openapiRequiredFields = new HashSet(0); - {{/hasRequired}} - } - - /** - * Validates the JSON Element and throws an exception if issues found - * - * @param jsonElement JSON Element - * @throws IOException if the JSON Element is invalid with respect to {{classname}} - */ - public static void validateJsonElement(JsonElement jsonElement) throws IOException { - if (jsonElement == null) { - if (!{{classname}}.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null - throw new IllegalArgumentException(String.format("The required field(s) %s in {{{classname}}} is not found in the empty JSON string", {{classname}}.openapiRequiredFields.toString())); - } - } - {{^hasChildren}} - {{^isAdditionalPropertiesTrue}} - - Set> entries = jsonElement.getAsJsonObject().entrySet(); - // check to see if the JSON string contains additional fields - for (Map.Entry entry : entries) { - if (!{{classname}}.openapiFields.contains(entry.getKey())) { - throw new IllegalArgumentException(String.format("The field `%s` in the JSON string is not defined in the `{{classname}}` properties. JSON: %s", entry.getKey(), jsonElement.toString())); - } - } - {{/isAdditionalPropertiesTrue}} - {{#requiredVars}} - {{#-first}} - - // check to make sure all required properties/fields are present in the JSON string - for (String requiredField : {{classname}}.openapiRequiredFields) { - if (jsonElement.getAsJsonObject().get(requiredField) == null) { - throw new IllegalArgumentException(String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())); - } - } - {{/-first}} - {{/requiredVars}} - {{/hasChildren}} - {{^discriminator}} - {{#hasVars}} - JsonObject jsonObj = jsonElement.getAsJsonObject(); - {{/hasVars}} - {{#vars}} - {{#isArray}} - {{#items.isModel}} - {{#required}} - // ensure the json data is an array - if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - - JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); - // validate the required field `{{{baseName}}}` (array) - for (int i = 0; i < jsonArray{{name}}.size(); i++) { - {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i)); - }; - {{/required}} - {{^required}} - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); - if (jsonArray{{name}} != null) { - // ensure the json data is an array - if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - - // validate the optional field `{{{baseName}}}` (array) - for (int i = 0; i < jsonArray{{name}}.size(); i++) { - {{{items.dataType}}}.validateJsonElement(jsonArray{{name}}.get(i)); - }; - } - } - {{/required}} - {{/items.isModel}} - {{^items.isModel}} - {{^required}} - // ensure the optional json data is an array if present - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull() && !jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/required}} - {{#required}} - // ensure the required json array is present - if (jsonObj.get("{{{baseName}}}") == null) { - throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`"); - } else if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/required}} - {{/items.isModel}} - {{/isArray}} - {{^isContainer}} - {{#isString}} - if ({{#notRequiredOrIsNullable}}(jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) && {{/notRequiredOrIsNullable}}!jsonObj.get("{{{baseName}}}").isJsonPrimitive()) { - throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); - } - {{/isString}} - {{#isModel}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isModel}} - {{#isEnum}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{datatypeWithEnum}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isEnum}} - {{#isEnumRef}} - {{#required}} - // validate the required field `{{{baseName}}}` - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - {{/required}} - {{^required}} - // validate the optional field `{{{baseName}}}` - if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { - {{{dataType}}}.validateJsonElement(jsonObj.get("{{{baseName}}}")); - } - {{/required}} - {{/isEnumRef}} - {{/isContainer}} - {{/vars}} - {{/discriminator}} - {{#hasChildren}} - {{#discriminator}} - - String discriminatorValue = jsonElement.getAsJsonObject().get("{{{propertyBaseName}}}").getAsString(); - switch (discriminatorValue) { - {{#mappedModels}} - case "{{mappingName}}": - {{modelName}}.validateJsonElement(jsonElement); - break; - {{/mappedModels}} - default: - throw new IllegalArgumentException(String.format("The value of the `{{{propertyBaseName}}}` field `%s` does not match any key defined in the discriminator's mapping.", discriminatorValue)); - } - {{/discriminator}} - {{/hasChildren}} - } - -{{^hasChildren}} - public static class CustomTypeAdapterFactory implements TypeAdapterFactory { - @SuppressWarnings("unchecked") - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { - return null; // this class only serializes '{{classname}}' and its subtypes - } - final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); - final TypeAdapter<{{classname}}> thisAdapter - = gson.getDelegateAdapter(this, TypeToken.get({{classname}}.class)); - - return (TypeAdapter) new TypeAdapter<{{classname}}>() { - @Override - public void write(JsonWriter out, {{classname}} value) throws IOException { - JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); - {{#isAdditionalPropertiesTrue}} - obj.remove("additionalProperties"); - // serialize additional properties - if (value.getAdditionalProperties() != null) { - for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { - if (entry.getValue() instanceof String) - obj.addProperty(entry.getKey(), (String) entry.getValue()); - else if (entry.getValue() instanceof Number) - obj.addProperty(entry.getKey(), (Number) entry.getValue()); - else if (entry.getValue() instanceof Boolean) - obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); - else if (entry.getValue() instanceof Character) - obj.addProperty(entry.getKey(), (Character) entry.getValue()); - else { - JsonElement jsonElement = gson.toJsonTree(entry.getValue()); - if (jsonElement.isJsonArray()) { - obj.add(entry.getKey(), jsonElement.getAsJsonArray()); - } else { - obj.add(entry.getKey(), jsonElement.getAsJsonObject()); - } - } - } - } - {{/isAdditionalPropertiesTrue}} - elementAdapter.write(out, obj); - } - - @Override - public {{classname}} read(JsonReader in) throws IOException { - JsonElement jsonElement = elementAdapter.read(in); -{{^vendorExtensions.x-skip-validation}} - validateJsonElement(jsonElement); -{{/vendorExtensions.x-skip-validation}} -{{#vendorExtensions.x-skip-validation}} - // vertex:TODO: Skipping validation during deserialization of the JSON element based on configuration - // validateJsonElement(jsonElement); -{{/vendorExtensions.x-skip-validation}} - {{#isAdditionalPropertiesTrue}} - JsonObject jsonObj = jsonElement.getAsJsonObject(); - // store additional fields in the deserialized instance - {{classname}} instance = thisAdapter.fromJsonTree(jsonObj); - for (Map.Entry entry : jsonObj.entrySet()) { - if (!openapiFields.contains(entry.getKey())) { - if (entry.getValue().isJsonPrimitive()) { // primitive type - if (entry.getValue().getAsJsonPrimitive().isString()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); - else if (entry.getValue().getAsJsonPrimitive().isNumber()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); - else if (entry.getValue().getAsJsonPrimitive().isBoolean()) - instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); - else - throw new IllegalArgumentException(String.format("The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); - } else if (entry.getValue().isJsonArray()) { - instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); - } else { // JSON object - instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); - } - } - } - return instance; - {{/isAdditionalPropertiesTrue}} - {{^isAdditionalPropertiesTrue}} - return thisAdapter.fromJsonTree(jsonElement); - {{/isAdditionalPropertiesTrue}} - } - - }.nullSafe(); - } - } -{{/hasChildren}} - - /** - * Create an instance of {{classname}} given an JSON string - * - * @param jsonString JSON string - * @return An instance of {{classname}} - * @throws IOException if the JSON string is invalid with respect to {{classname}} - */ - public static {{{classname}}} fromJson(String jsonString) throws IOException { - return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); - } - - /** - * Convert an instance of {{classname}} to an JSON string - * - * @return JSON string - */ - public String toJson() { - return JSON.getGson().toJson(this); - } -} \ No newline at end of file