From a5d6d230fcfcef192c47162085906866ca02fdf7 Mon Sep 17 00:00:00 2001 From: Cameron Rushton Date: Tue, 1 Mar 2022 17:46:03 -0500 Subject: [PATCH] fix: avro schema union types generate object type (#250) * initial implementation; needs testing and clean up * added toString() call on objects in toString() method; created snapshot * fix linting issues --- filters/all.js | 3 + partials/java-class | 5 ++ test/__snapshots__/integration.test.js.snap | 66 +++++++++++++++++++++ test/integration.test.js | 9 +++ test/mocks/avro-union-object.yaml | 42 +++++++++++++ 5 files changed, 125 insertions(+) create mode 100644 test/mocks/avro-union-object.yaml diff --git a/filters/all.js b/filters/all.js index 46dc9afc..d82b3279 100644 --- a/filters/all.js +++ b/filters/all.js @@ -336,6 +336,9 @@ function fixType([name, javaName, property]) { if (property.enum()) { debugType('It is an enum.'); typeName = _.upperFirst(javaName); + } else if (property.oneOf() || property.anyOf() || property.allOf()) { + // Picking a type for the user may be difficult - especially since the first avro union value must be the default value which is normally of type null. + typeName = 'Object'; } else { // check to see if it's a ref to another schema. typeName = property.ext('x-parser-schema-id'); diff --git a/partials/java-class b/partials/java-class index a65d661a..ba5e968f 100644 --- a/partials/java-class +++ b/partials/java-class @@ -75,7 +75,12 @@ {%- set propModelClass = {schema: prop, schemaName: name} | getModelClass %} {%- set realClassName = propModelClass.getClassName() %} {%- set variableName = realClassName | identifierName %} +{%- set typeInfo = [realClassName, realClassName, prop] | fixType -%} +{%- set type = typeInfo[0] %} {{ indent3 }}+ " {{ variableName }}: " + {{ variableName }} +{%- if type === 'Object' -%} +.toString() +{%- endif -%} {%- endfor %} {%- if modelClass.isSubClass() %} {{ indent3 }}+ " super: " + super.toString(){% endif %} diff --git a/test/__snapshots__/integration.test.js.snap b/test/__snapshots__/integration.test.js.snap index df84cfd7..16521968 100644 --- a/test/__snapshots__/integration.test.js.snap +++ b/test/__snapshots__/integration.test.js.snap @@ -1801,3 +1801,69 @@ public class JobAcknowledge { } " `; + +exports[`template integration tests using the generator should return object when avro union type is used specifying many possible types 1`] = ` +"package com.example.api.jobOrder; + + +import com.fasterxml.jackson.annotation.JsonInclude; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class JobOrder { + + public JobOrder () { + } + + public JobOrder ( + String jobOrderId, + Object jobOrderDescription, + Object jobOrderLongDescription) { + this.jobOrderId = jobOrderId; + this.jobOrderDescription = jobOrderDescription; + this.jobOrderLongDescription = jobOrderLongDescription; + } + + private String jobOrderId; + private Object jobOrderDescription; + private Object jobOrderLongDescription; + public String getJobOrderId() { + return jobOrderId; + } + + public JobOrder setJobOrderId(String jobOrderId) { + this.jobOrderId = jobOrderId; + return this; + } + + + public Object getJobOrderDescription() { + return jobOrderDescription; + } + + public JobOrder setJobOrderDescription(Object jobOrderDescription) { + this.jobOrderDescription = jobOrderDescription; + return this; + } + + + public Object getJobOrderLongDescription() { + return jobOrderLongDescription; + } + + public JobOrder setJobOrderLongDescription(Object jobOrderLongDescription) { + this.jobOrderLongDescription = jobOrderLongDescription; + return this; + } + + public String toString() { + return \\"JobOrder [\\" + + \\" jobOrderId: \\" + jobOrderId + + \\" jobOrderDescription: \\" + jobOrderDescription.toString() + + \\" jobOrderLongDescription: \\" + jobOrderLongDescription.toString() + + \\" ]\\"; + } +} +" +`; diff --git a/test/integration.test.js b/test/integration.test.js index fa94ca63..0703dce2 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -183,4 +183,13 @@ describe('template integration tests using the generator', () => { ]; await assertExpectedFiles(validatedFiles); }); + + it('should return object when avro union type is used specifying many possible types', async () => { + await generate('mocks/avro-union-object.yaml'); + + const validatedFiles = [ + 'src/main/java/com/example/api/jobOrder/JobOrder.java' + ]; + await assertExpectedFiles(validatedFiles); + }); }); diff --git a/test/mocks/avro-union-object.yaml b/test/mocks/avro-union-object.yaml new file mode 100644 index 00000000..bc208a11 --- /dev/null +++ b/test/mocks/avro-union-object.yaml @@ -0,0 +1,42 @@ +--- +components: + schemas: {} + messages: + JobOrder: + payload: + name: "JobOrder" + namespace: "com.example.api.jobOrder" + doc: "JobOrder" + type: "record" + fields: + - name: "jobOrderId" + doc: "JobOrderID" + type: "string" + - name: "jobOrderDescription" + doc: "JobOrderDescription" + type: + - "null" + - "string" + - name: "jobOrderLongDescription" + doc: "JobOrderLongDescription" + type: + - "null" + - "string" + schemaFormat: "application/vnd.apache.avro+json;version=1.9.0" + contentType: "application/vnd.apache.avro+json" +servers: + production: + protocol: "kafka" + url: "xxxxx.us-east-2.aws.confluent.cloud:9092" +channels: + test.jobs.order: + subscribe: + message: + $ref: "#/components/messages/JobOrder" +asyncapi: "2.0.0" +info: + x-generated-time: "2022-02-24 01:18 UTC" + description: "" + title: "Union Types" + x-view: "provider" + version: "1"