diff --git a/.gitignore b/.gitignore index fe92ffcf..87cb2625 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules test/temp -coverage \ No newline at end of file +coverage +**/.DS_Store +**/.vscode \ No newline at end of file diff --git a/hooks/pre-process.js b/hooks/pre-process.js index 7b31b924..bcf388be 100644 --- a/hooks/pre-process.js +++ b/hooks/pre-process.js @@ -1,15 +1,48 @@ const ApplicationModel = require('../lib/applicationModel.js'); +const _ = require('lodash'); -module.exports = { - 'generate:before': generator => { - generator.asyncapi.allSchemas().forEach((schema, schemaName) => { - // The generator will create file names based on the schema's $id. Instead of guessing what the generator named the file so we can fix it in post, - // ... it's easier to process $id here first. Since we don't use it, removing it is easiest. - if (schema.$id()) { - delete schema._json.$id; +function setSchemaIdsForFileName(asyncapi) { + asyncapi.allSchemas().forEach((schema, schemaName) => { + // If we leave the $id the way it is, the generator will name the schema files what their $id is, which is always a bad idea. + // So we leave it in, but $id is going to be changed to be the class name we want. + // If we remove the $id and there's no x-parser-schema-id, then it wont be returned by allSchemas(). + if (schema.$id()) { + // Assuming one of x-parser-schema-id and $id must be present. + let classNameForGenerator; + const parserSchemaId = schema.ext('x-parser-schema-id'); + classNameForGenerator = parserSchemaId ? parserSchemaId : _.camelCase(schema.$id().substring(schema.$id().lastIndexOf('/') + 1)); + + if (classNameForGenerator === 'items') { + const parentSchema = schema.options?.parent; + const parentSchemaItems = parentSchema?.items(); + if (parentSchemaItems?._json?.$id === schema.$id()) { + const parentParserSchemaId = parentSchema.ext('x-parser-schema-id'); + classNameForGenerator = parentParserSchemaId ? parentParserSchemaId : _.camelCase(parentSchema.$id().substring(parentSchema.$id().lastIndexOf('/') + 1)); + // If we come across this schema later in the code generator, we'll know to rename it to its parent because the proper settings will be set in the model class. + schema._json['x-model-class-name'] = classNameForGenerator; + classNameForGenerator += 'Items'; + } } - }); + schema._json.$id = classNameForGenerator; + } + }); +} + +function setSchemaIdsForFileNameIncludingDuplicates(asyncapi) { + // We do this multiple times because allSchemas() returns a list of deduplicated schemas, so if we change the $id of a schema, + // we wont change any of the duplicates. We continue until there are no more duplicates to change. + let numSchemas; + let newNumSchemas; + do { + numSchemas = asyncapi.allSchemas().size; + setSchemaIdsForFileName(asyncapi); + newNumSchemas = asyncapi.allSchemas().size; + } while (numSchemas !== newNumSchemas); +} +module.exports = { + 'generate:before': generator => { + setSchemaIdsForFileNameIncludingDuplicates(generator.asyncapi); ApplicationModel.asyncapi = generator.asyncapi; } }; \ No newline at end of file diff --git a/lib/applicationModel.js b/lib/applicationModel.js index 16a1e06e..ff2bc22d 100644 --- a/lib/applicationModel.js +++ b/lib/applicationModel.js @@ -30,7 +30,7 @@ class ApplicationModel { } // Using x-parser-schema-id didn't work for us, fall back to trying to get at least something using the provided name. if (!modelClass) { - modelClass = this.modelClassMap[schemaName]; + modelClass = this.modelClassMap[schemaName] || this.modelClassMap[_.camelCase(schemaName)]; } debugApplicationModel(`returning modelClass for caller ${this.caller} ${schemaName}`); debugApplicationModel(modelClass); @@ -42,25 +42,26 @@ class ApplicationModel { } setupSuperClassMap() { - if (!this.superClassMap) { - this.superClassMap = new Map(); - this.anonymousSchemaToSubClassMap = new Map(); - debugApplicationModel('-------- SCHEMAS -------------'); - debugApplicationModel(ApplicationModel.asyncapi.allSchemas()); - ApplicationModel.asyncapi.allSchemas().forEach((schema, schemaName) => { - debugApplicationModel(`${schemaName}:`); - debugApplicationModel(schema); - const allOf = schema.allOf(); - if (allOf) { - this.handleAllOfSchema(schema, schemaName, allOf); - } - }); - debugApplicationModel('-----------------------------'); - debugApplicationModel('superclassMap:'); - debugApplicationModel(this.superClassMap); - debugApplicationModel('anonymousSchemaToSubClassMap:'); - debugApplicationModel(this.anonymousSchemaToSubClassMap); + if (this.superClassMap) { + return; } + this.superClassMap = new Map(); + this.anonymousSchemaToSubClassMap = new Map(); + debugApplicationModel('-------- SCHEMAS -------------'); + debugApplicationModel(ApplicationModel.asyncapi.allSchemas()); + ApplicationModel.asyncapi.allSchemas().forEach((schema, schemaName) => { + debugApplicationModel(`${schemaName}:`); + debugApplicationModel(schema); + const allOf = schema.allOf(); + if (allOf) { + this.handleAllOfSchema(schema, schemaName, allOf); + } + }); + debugApplicationModel('-----------------------------'); + debugApplicationModel('superclassMap:'); + debugApplicationModel(this.superClassMap); + debugApplicationModel('anonymousSchemaToSubClassMap:'); + debugApplicationModel(this.anonymousSchemaToSubClassMap); } handleAllOfSchema(schema, schemaName, allOfSchema) { @@ -89,54 +90,19 @@ class ApplicationModel { } setupModelClassMap() { - if (!this.modelClassMap) { - this.modelClassMap = new Map(); - this.nameToSchemaMap = new Map(); - // Register all schemas first, then check the anonymous schemas for duplicates - ApplicationModel.asyncapi.allSchemas().forEach((schema, name) => { - debugApplicationModel(`setupModelClassMap ${name} type ${schema.type()}`); - this.registerSchemaNameToModelClass(schema, name); - this.nameToSchemaMap[name] = schema; - }); - - ApplicationModel.asyncapi.allSchemas().forEach((schema, schemaName) => { - debugApplicationModel(`setupModelClassMap anonymous schemas ${schemaName} type ${schema.type()}`); - this.registerSchemasInProperties(schema); - this.registerSchemasInAllOf(schema); - }); - debugApplicationModel('modelClassMap:'); - debugApplicationModel(this.modelClassMap); - } - } - - registerSchemasInProperties(schema) { - if (!!Object.keys(schema.properties()).length) { - // Each property name is the name of a schema. It should also have an x-parser-schema-id name. We'll be adding duplicate mappings (two mappings to the same model class) since the anon schemas do have names - Object.keys(schema.properties()).forEach(property => { - const innerSchema = schema.properties()[property]; - const innerSchemaParserId = innerSchema.ext('x-parser-schema-id'); - const existingModelClass = this.modelClassMap[innerSchemaParserId]; - if (existingModelClass) { - this.modelClassMap[property] = existingModelClass; - } else { - this.registerSchemaNameToModelClass(innerSchema, property); - } - }); - } - } - - registerSchemasInAllOf(schema) { - const allOf = schema.allOf(); - debugApplicationModel('allOf:'); - debugApplicationModel(allOf); - if (allOf) { - allOf.forEach(innerSchema => { - const name = innerSchema.ext('x-parser-schema-id'); - if (this.isAnonymousSchema(name) && innerSchema.type() === 'object') { - this.registerSchemaNameToModelClass(innerSchema, name); - } - }); + if (this.modelClassMap) { + return; } + this.modelClassMap = new Map(); + this.nameToSchemaMap = new Map(); + // Register all schemas recursively as a flat map of name -> ModelClass + ApplicationModel.asyncapi.allSchemas().forEach((schema, name) => { + debugApplicationModel(`setupModelClassMap ${name} type ${schema.type()}`); + this.registerSchemaNameToModelClass(schema, name); + this.nameToSchemaMap[name] = schema; + }); + debugApplicationModel('modelClassMap:'); + debugApplicationModel(this.modelClassMap); } isAnonymousSchema(schemaName) { @@ -158,7 +124,12 @@ class ApplicationModel { modelClass.setCanBeInnerClass(false); } - const { className, javaPackage } = scsLib.stripPackageName(schemaName); + const classNameAndLocation = scsLib.stripPackageName(schemaName); + let className = classNameAndLocation.className; + const javaPackage = classNameAndLocation.javaPackage; + if (schema._json['x-model-class-name']) { + className = schema._json['x-model-class-name']; + } modelClass.setJavaPackage(javaPackage); modelClass.setClassName(className); debugApplicationModel(`schemaName ${schemaName} className: ${modelClass.getClassName()} super: ${modelClass.getSuperClassName()} javaPackage: ${javaPackage}`); diff --git a/test/__snapshots__/integration.test.js.snap b/test/__snapshots__/integration.test.js.snap index e7978896..2bb74dff 100644 --- a/test/__snapshots__/integration.test.js.snap +++ b/test/__snapshots__/integration.test.js.snap @@ -130,6 +130,329 @@ public class User { " `; +exports[`template integration tests using the generator should generate a class for a schema property that is an array of objects 1`] = ` +" + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.function.StreamBridge; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; + +@SpringBootApplication +public class Application { + + private static final Logger logger = LoggerFactory.getLogger(Application.class); + + @Autowired + private StreamBridge streamBridge; + + public static void main(String[] args) { + SpringApplication.run(Application.class); + } + + + public void sendAcmeRideshareBillingReceiptCreated001RegionChargifyRideId( + RideReceipt payload, String region, String rideId + ) { + String topic = String.format(\\"acme/rideshare/billing/receipt/created/0.0.1/%s/chargify/%s\\", + region, rideId); + streamBridge.send(topic, payload); + } +} +" +`; + +exports[`template integration tests using the generator should generate a class for a schema property that is an array of objects 2`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ChargeAdjustments { + + public ChargeAdjustments () { + } + + public ChargeAdjustments ( + String amount, + String name, + String type) { + this.amount = amount; + this.name = name; + this.type = type; + } + + private String amount; + private String name; + private String type; + public String getAmount() { + return amount; + } + + public ChargeAdjustments setAmount(String amount) { + this.amount = amount; + return this; + } + + + public String getName() { + return name; + } + + public ChargeAdjustments setName(String name) { + this.name = name; + return this; + } + + + public String getType() { + return type; + } + + public ChargeAdjustments setType(String type) { + this.type = type; + return this; + } + + public String toString() { + return \\"ChargeAdjustments [\\" + + \\" amount: \\" + amount + + \\" name: \\" + name + + \\" type: \\" + type + + \\" ]\\"; + } +} +" +`; + +exports[`template integration tests using the generator should generate a class for a schema property that is an array of objects 3`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RideReceipt { + + public RideReceipt () { + } + + public RideReceipt ( + String totalOwed, + String duration, + TestObject testObject, + ChargeAdjustments[] chargeAdjustments, + String currencyCode) { + this.totalOwed = totalOwed; + this.duration = duration; + this.testObject = testObject; + this.chargeAdjustments = chargeAdjustments; + this.currencyCode = currencyCode; + } + + @JsonProperty(\\"total_owed\\") + private String totalOwed; + private String duration; + @JsonProperty(\\"test_object\\") + private TestObject testObject; + @JsonProperty(\\"charge_adjustments\\") + private ChargeAdjustments[] chargeAdjustments; + @JsonProperty(\\"currency_code\\") + private String currencyCode; + public String getTotalOwed() { + return totalOwed; + } + + public RideReceipt setTotalOwed(String totalOwed) { + this.totalOwed = totalOwed; + return this; + } + + + public String getDuration() { + return duration; + } + + public RideReceipt setDuration(String duration) { + this.duration = duration; + return this; + } + + + public TestObject getTestObject() { + return testObject; + } + + public RideReceipt setTestObject(TestObject testObject) { + this.testObject = testObject; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class TestObject { + + public TestObject () { + } + + public TestObject ( + String field1) { + this.field1 = field1; + } + + private String field1; + public String getField1() { + return field1; + } + + public TestObject setField1(String field1) { + this.field1 = field1; + return this; + } + + public String toString() { + return \\"TestObject [\\" + + \\" field1: \\" + field1 + + \\" ]\\"; + } + } + + public ChargeAdjustments[] getChargeAdjustments() { + return chargeAdjustments; + } + + public RideReceipt setChargeAdjustments(ChargeAdjustments[] chargeAdjustments) { + this.chargeAdjustments = chargeAdjustments; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class ChargeAdjustments { + + public ChargeAdjustments () { + } + public ChargeAdjustments ( + String amount, + String name, + String type) { + this.amount = amount; + this.name = name; + this.type = type; + } + + + private String amount; + private String name; + private String type; + public String getAmount() { + return amount; + } + + public ChargeAdjustments setAmount(String amount) { + this.amount = amount; + return this; + } + + + public String getName() { + return name; + } + + public ChargeAdjustments setName(String name) { + this.name = name; + return this; + } + + + public String getType() { + return type; + } + + public ChargeAdjustments setType(String type) { + this.type = type; + return this; + } + + public String toString() { + return \\"ChargeAdjustments [\\" + + \\" amount: \\" + amount + + \\" name: \\" + name + + \\" type: \\" + type + + \\" ]\\"; + } + } + + public String getCurrencyCode() { + return currencyCode; + } + + public RideReceipt setCurrencyCode(String currencyCode) { + this.currencyCode = currencyCode; + return this; + } + + public String toString() { + return \\"RideReceipt [\\" + + \\" totalOwed: \\" + totalOwed + + \\" duration: \\" + duration + + \\" testObject: \\" + testObject + + \\" chargeAdjustments: \\" + chargeAdjustments + + \\" currencyCode: \\" + currencyCode + + \\" ]\\"; + } +} +" +`; + +exports[`template integration tests using the generator should generate a class for a schema property that is an array of objects 4`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TestObject { + + public TestObject () { + } + + public TestObject ( + String field1) { + this.field1 = field1; + } + + private String field1; + public String getField1() { + return field1; + } + + public TestObject setField1(String field1) { + this.field1 = field1; + return this; + } + + public String toString() { + return \\"TestObject [\\" + + \\" field1: \\" + field1 + + \\" ]\\"; + } +} +" +`; + exports[`template integration tests using the generator should generate a comment for a consumer receiving multiple messages 1`] = ` " @@ -797,110 +1120,617 @@ public class SubObject { " `; -exports[`template integration tests using the generator should generate code using schemas that have $id set 1`] = ` -" +exports[`template integration tests using the generator should generate extra config when using the paramatersToHeaders parameter 1`] = ` +"package com.acme; import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.function.StreamBridge; import org.springframework.context.annotation.Bean; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; @SpringBootApplication public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); + @Autowired + private StreamBridge streamBridge; + public static void main(String[] args) { SpringApplication.run(Application.class); } + @Bean - public Consumer acmeRideshareRideRequested001Consumer() { + public Consumer> testLevel1MessageIdOperationConsumer() { return data -> { // Add business logic here. logger.info(data.toString()); }; } + public void sendTestLevel1MessageIdOperation( + MySchema payload, String messageId, String operation + ) { + String topic = String.format(\\"testLevel1/%s/%s\\", + messageId, operation); + streamBridge.send(topic, payload); + } } " `; -exports[`template integration tests using the generator should generate code using schemas that have $id set 2`] = ` +exports[`template integration tests using the generator should generate extra config when using the paramatersToHeaders parameter 2`] = ` +"spring: + cloud: + function: + configuration: + testLevel1MessageIdOperationConsumer: + input-header-mapping-expression: + messageId: 'headers.solace_destination.getName.split(\\"/\\")[1]' + operation: 'headers.solace_destination.getName.split(\\"/\\")[2]' + definition: testLevel1MessageIdOperationConsumer + stream: + bindings: + testLevel1MessageIdOperationConsumer-in-0: + destination: testLevel1/*/* + binders: + solace-binder: + type: solace + environment: + solace: + java: + host: testVmrUri + msgVpn: vpnName + clientUsername: user + clientPassword: test +logging: + level: + root: info + org: + springframework: info + " +`; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; +exports[`template integration tests using the generator should generate one class for a schema with multiple references to it in the asyncapi document 1`] = ` +" + +import java.util.function.Consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.stream.function.StreamBridge; +import org.springframework.context.annotation.Bean; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; + +@SpringBootApplication +public class Application { + + private static final Logger logger = LoggerFactory.getLogger(Application.class); + + @Autowired + private StreamBridge streamBridge; + + public static void main(String[] args) { + SpringApplication.run(Application.class); + } + + + @Bean + public Consumer taxinycOpsRideUpdatedV1RideStatusDriverIdPassengerIdConsumer() { + return data -> { + // Add business logic here. + logger.info(data.toString()); + }; + } + + public void sendTaxinycBackofficePaymentChargedV1PaymentStatusDriverIdPassengerId( + PaymentCharged payload, String paymentStatus, String driverId, String passengerId + ) { + String topic = String.format(\\"taxinyc/backoffice/payment/charged/v1/%s/%s/%s\\", + paymentStatus, driverId, passengerId); + streamBridge.send(topic, payload); + } +} +" +`; + +exports[`template integration tests using the generator should generate one class for a schema with multiple references to it in the asyncapi document 2`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Driver { + + public Driver () { + } + + public Driver ( + Integer driverId, + java.math.BigDecimal rating, + String lastName, + String carClass, + String firstName) { + this.driverId = driverId; + this.rating = rating; + this.lastName = lastName; + this.carClass = carClass; + this.firstName = firstName; + } + + @JsonProperty(\\"driver_id\\") + private Integer driverId; + private java.math.BigDecimal rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"car_class\\") + private String carClass; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getDriverId() { + return driverId; + } + + public Driver setDriverId(Integer driverId) { + this.driverId = driverId; + return this; + } + + + public java.math.BigDecimal getRating() { + return rating; + } + + public Driver setRating(java.math.BigDecimal rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Driver setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getCarClass() { + return carClass; + } + + public Driver setCarClass(String carClass) { + this.carClass = carClass; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Driver setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Driver [\\" + + \\" driverId: \\" + driverId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" carClass: \\" + carClass + + \\" firstName: \\" + firstName + + \\" ]\\"; + } +} +" +`; + +exports[`template integration tests using the generator should generate one class for a schema with multiple references to it in the asyncapi document 3`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Passenger { + + public Passenger () { + } + + public Passenger ( + Integer passengerId, + java.math.BigDecimal rating, + String lastName, + String firstName) { + this.passengerId = passengerId; + this.rating = rating; + this.lastName = lastName; + this.firstName = firstName; + } + + @JsonProperty(\\"passenger_id\\") + private Integer passengerId; + private java.math.BigDecimal rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getPassengerId() { + return passengerId; + } + + public Passenger setPassengerId(Integer passengerId) { + this.passengerId = passengerId; + return this; + } + + + public java.math.BigDecimal getRating() { + return rating; + } + + public Passenger setRating(java.math.BigDecimal rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Passenger setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Passenger setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Passenger [\\" + + \\" passengerId: \\" + passengerId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" firstName: \\" + firstName + + \\" ]\\"; + } +} +" +`; + +exports[`template integration tests using the generator should generate one class for a schema with multiple references to it in the asyncapi document 4`] = ` +" + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; @JsonInclude(JsonInclude.Include.NON_NULL) -public class DefaultMessageSchema { +public class PaymentCharged { - public DefaultMessageSchema () { + public PaymentCharged () { } - public DefaultMessageSchema ( - java.math.BigDecimal avgMeterReading, - Integer windowDurationSec, - java.math.BigDecimal avgPassengerCount, - Integer windowRideCount, + public PaymentCharged ( + Integer rideId, + String entityType, + java.math.BigDecimal amountCharged, + Driver driver, + String paymentChargedId, + Passenger passenger, + String paymentStatus, + String invoiceSystemId, + String informationSource, String timestamp) { - this.avgMeterReading = avgMeterReading; - this.windowDurationSec = windowDurationSec; - this.avgPassengerCount = avgPassengerCount; - this.windowRideCount = windowRideCount; + this.rideId = rideId; + this.entityType = entityType; + this.amountCharged = amountCharged; + this.driver = driver; + this.paymentChargedId = paymentChargedId; + this.passenger = passenger; + this.paymentStatus = paymentStatus; + this.invoiceSystemId = invoiceSystemId; + this.informationSource = informationSource; this.timestamp = timestamp; } - @JsonProperty(\\"avg_meter_reading\\") - private java.math.BigDecimal avgMeterReading; - @JsonProperty(\\"window_duration_sec\\") - private Integer windowDurationSec; - @JsonProperty(\\"avg_passenger_count\\") - private java.math.BigDecimal avgPassengerCount; - @JsonProperty(\\"window_ride_count\\") - private Integer windowRideCount; + @JsonProperty(\\"ride_id\\") + private Integer rideId; + @JsonProperty(\\"entity_type\\") + private String entityType; + @JsonProperty(\\"amount_charged\\") + private java.math.BigDecimal amountCharged; + private Driver driver; + @JsonProperty(\\"payment_charged_id\\") + private String paymentChargedId; + private Passenger passenger; + @JsonProperty(\\"payment_status\\") + private String paymentStatus; + @JsonProperty(\\"invoice_system_id\\") + private String invoiceSystemId; + @JsonProperty(\\"information_source\\") + private String informationSource; private String timestamp; - public java.math.BigDecimal getAvgMeterReading() { - return avgMeterReading; + public Integer getRideId() { + return rideId; + } + + public PaymentCharged setRideId(Integer rideId) { + this.rideId = rideId; + return this; + } + + + public String getEntityType() { + return entityType; + } + + public PaymentCharged setEntityType(String entityType) { + this.entityType = entityType; + return this; + } + + + public java.math.BigDecimal getAmountCharged() { + return amountCharged; + } + + public PaymentCharged setAmountCharged(java.math.BigDecimal amountCharged) { + this.amountCharged = amountCharged; + return this; + } + + + public Driver getDriver() { + return driver; + } + + public PaymentCharged setDriver(Driver driver) { + this.driver = driver; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Driver { + + public Driver () { + } + + public Driver ( + Integer driverId, + Integer rating, + String lastName, + String carClass, + String firstName) { + this.driverId = driverId; + this.rating = rating; + this.lastName = lastName; + this.carClass = carClass; + this.firstName = firstName; + } + + @JsonProperty(\\"driver_id\\") + private Integer driverId; + private Integer rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"car_class\\") + private String carClass; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getDriverId() { + return driverId; + } + + public Driver setDriverId(Integer driverId) { + this.driverId = driverId; + return this; + } + + + public Integer getRating() { + return rating; + } + + public Driver setRating(Integer rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Driver setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getCarClass() { + return carClass; + } + + public Driver setCarClass(String carClass) { + this.carClass = carClass; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Driver setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Driver [\\" + + \\" driverId: \\" + driverId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" carClass: \\" + carClass + + \\" firstName: \\" + firstName + + \\" ]\\"; + } + } + + public String getPaymentChargedId() { + return paymentChargedId; } - public DefaultMessageSchema setAvgMeterReading(java.math.BigDecimal avgMeterReading) { - this.avgMeterReading = avgMeterReading; + public PaymentCharged setPaymentChargedId(String paymentChargedId) { + this.paymentChargedId = paymentChargedId; return this; } - public Integer getWindowDurationSec() { - return windowDurationSec; + public Passenger getPassenger() { + return passenger; + } + + public PaymentCharged setPassenger(Passenger passenger) { + this.passenger = passenger; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Passenger { + + public Passenger () { + } + + public Passenger ( + Integer passengerId, + Integer rating, + String lastName, + String firstName) { + this.passengerId = passengerId; + this.rating = rating; + this.lastName = lastName; + this.firstName = firstName; + } + + @JsonProperty(\\"passenger_id\\") + private Integer passengerId; + private Integer rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getPassengerId() { + return passengerId; + } + + public Passenger setPassengerId(Integer passengerId) { + this.passengerId = passengerId; + return this; + } + + + public Integer getRating() { + return rating; + } + + public Passenger setRating(Integer rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Passenger setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Passenger setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Passenger [\\" + + \\" passengerId: \\" + passengerId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" firstName: \\" + firstName + + \\" ]\\"; + } } - public DefaultMessageSchema setWindowDurationSec(Integer windowDurationSec) { - this.windowDurationSec = windowDurationSec; + public String getPaymentStatus() { + return paymentStatus; + } + + public PaymentCharged setPaymentStatus(String paymentStatus) { + this.paymentStatus = paymentStatus; return this; } - public java.math.BigDecimal getAvgPassengerCount() { - return avgPassengerCount; + public String getInvoiceSystemId() { + return invoiceSystemId; } - public DefaultMessageSchema setAvgPassengerCount(java.math.BigDecimal avgPassengerCount) { - this.avgPassengerCount = avgPassengerCount; + public PaymentCharged setInvoiceSystemId(String invoiceSystemId) { + this.invoiceSystemId = invoiceSystemId; return this; } - public Integer getWindowRideCount() { - return windowRideCount; + public String getInformationSource() { + return informationSource; } - public DefaultMessageSchema setWindowRideCount(Integer windowRideCount) { - this.windowRideCount = windowRideCount; + public PaymentCharged setInformationSource(String informationSource) { + this.informationSource = informationSource; return this; } @@ -909,17 +1739,22 @@ public class DefaultMessageSchema { return timestamp; } - public DefaultMessageSchema setTimestamp(String timestamp) { + public PaymentCharged setTimestamp(String timestamp) { this.timestamp = timestamp; return this; } public String toString() { - return \\"DefaultMessageSchema [\\" - + \\" avgMeterReading: \\" + avgMeterReading - + \\" windowDurationSec: \\" + windowDurationSec - + \\" avgPassengerCount: \\" + avgPassengerCount - + \\" windowRideCount: \\" + windowRideCount + return \\"PaymentCharged [\\" + + \\" rideId: \\" + rideId + + \\" entityType: \\" + entityType + + \\" amountCharged: \\" + amountCharged + + \\" driver: \\" + driver + + \\" paymentChargedId: \\" + paymentChargedId + + \\" passenger: \\" + passenger + + \\" paymentStatus: \\" + paymentStatus + + \\" invoiceSystemId: \\" + invoiceSystemId + + \\" informationSource: \\" + informationSource + \\" timestamp: \\" + timestamp + \\" ]\\"; } @@ -927,83 +1762,394 @@ public class DefaultMessageSchema { " `; -exports[`template integration tests using the generator should generate extra config when using the paramatersToHeaders parameter 1`] = ` -"package com.acme; +exports[`template integration tests using the generator should generate one class for a schema with multiple references to it in the asyncapi document 5`] = ` +" -import java.util.function.Consumer; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.stream.function.StreamBridge; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -@SpringBootApplication -public class Application { - private static final Logger logger = LoggerFactory.getLogger(Application.class); +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RideUpdated1 { + + public RideUpdated1 () { + } + + public RideUpdated1 ( + String rideId, + Integer heading, + java.math.BigDecimal latitude, + Integer passengerCount, + Integer pointIdx, + String informationSource, + Integer speed, + Driver driver, + Passenger passenger, + java.math.BigDecimal meterIncrement, + java.math.BigDecimal longitude, + String timestamp, + java.math.BigDecimal meterReading, + RideStatus rideStatus) { + this.rideId = rideId; + this.heading = heading; + this.latitude = latitude; + this.passengerCount = passengerCount; + this.pointIdx = pointIdx; + this.informationSource = informationSource; + this.speed = speed; + this.driver = driver; + this.passenger = passenger; + this.meterIncrement = meterIncrement; + this.longitude = longitude; + this.timestamp = timestamp; + this.meterReading = meterReading; + this.rideStatus = rideStatus; + } + + @JsonProperty(\\"ride_id\\") + private String rideId; + private Integer heading; + private java.math.BigDecimal latitude; + @JsonProperty(\\"passenger_count\\") + private Integer passengerCount; + @JsonProperty(\\"point_idx\\") + private Integer pointIdx; + @JsonProperty(\\"information_source\\") + private String informationSource; + private Integer speed; + private Driver driver; + private Passenger passenger; + @JsonProperty(\\"meter_increment\\") + private java.math.BigDecimal meterIncrement; + private java.math.BigDecimal longitude; + private String timestamp; + @JsonProperty(\\"meter_reading\\") + private java.math.BigDecimal meterReading; + @JsonProperty(\\"ride_status\\") + private RideStatus rideStatus; + public String getRideId() { + return rideId; + } - @Autowired - private StreamBridge streamBridge; + public RideUpdated1 setRideId(String rideId) { + this.rideId = rideId; + return this; + } - public static void main(String[] args) { - SpringApplication.run(Application.class); + + public Integer getHeading() { + return heading; } + public RideUpdated1 setHeading(Integer heading) { + this.heading = heading; + return this; + } - @Bean - public Consumer> testLevel1MessageIdOperationConsumer() { - return data -> { - // Add business logic here. - logger.info(data.toString()); - }; + + public java.math.BigDecimal getLatitude() { + return latitude; } - public void sendTestLevel1MessageIdOperation( - MySchema payload, String messageId, String operation - ) { - String topic = String.format(\\"testLevel1/%s/%s\\", - messageId, operation); - streamBridge.send(topic, payload); + public RideUpdated1 setLatitude(java.math.BigDecimal latitude) { + this.latitude = latitude; + return this; } -} -" -`; -exports[`template integration tests using the generator should generate extra config when using the paramatersToHeaders parameter 2`] = ` -"spring: - cloud: - function: - configuration: - testLevel1MessageIdOperationConsumer: - input-header-mapping-expression: - messageId: 'headers.solace_destination.getName.split(\\"/\\")[1]' - operation: 'headers.solace_destination.getName.split(\\"/\\")[2]' - definition: testLevel1MessageIdOperationConsumer - stream: - bindings: - testLevel1MessageIdOperationConsumer-in-0: - destination: testLevel1/*/* - binders: - solace-binder: - type: solace - environment: - solace: - java: - host: testVmrUri - msgVpn: vpnName - clientUsername: user - clientPassword: test -logging: - level: - root: info - org: - springframework: info + public Integer getPassengerCount() { + return passengerCount; + } + + public RideUpdated1 setPassengerCount(Integer passengerCount) { + this.passengerCount = passengerCount; + return this; + } + + + public Integer getPointIdx() { + return pointIdx; + } + + public RideUpdated1 setPointIdx(Integer pointIdx) { + this.pointIdx = pointIdx; + return this; + } + + + public String getInformationSource() { + return informationSource; + } + + public RideUpdated1 setInformationSource(String informationSource) { + this.informationSource = informationSource; + return this; + } + + + public Integer getSpeed() { + return speed; + } + + public RideUpdated1 setSpeed(Integer speed) { + this.speed = speed; + return this; + } + + + public Driver getDriver() { + return driver; + } + + public RideUpdated1 setDriver(Driver driver) { + this.driver = driver; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Driver { + + public Driver () { + } + + public Driver ( + Integer driverId, + java.math.BigDecimal rating, + String lastName, + String carClass, + String firstName) { + this.driverId = driverId; + this.rating = rating; + this.lastName = lastName; + this.carClass = carClass; + this.firstName = firstName; + } + + @JsonProperty(\\"driver_id\\") + private Integer driverId; + private java.math.BigDecimal rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"car_class\\") + private String carClass; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getDriverId() { + return driverId; + } + + public Driver setDriverId(Integer driverId) { + this.driverId = driverId; + return this; + } + + + public java.math.BigDecimal getRating() { + return rating; + } + + public Driver setRating(java.math.BigDecimal rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Driver setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getCarClass() { + return carClass; + } + + public Driver setCarClass(String carClass) { + this.carClass = carClass; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Driver setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Driver [\\" + + \\" driverId: \\" + driverId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" carClass: \\" + carClass + + \\" firstName: \\" + firstName + + \\" ]\\"; + } + } + + public Passenger getPassenger() { + return passenger; + } + + public RideUpdated1 setPassenger(Passenger passenger) { + this.passenger = passenger; + return this; + } + + + + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class Passenger { + + public Passenger () { + } + + public Passenger ( + Integer passengerId, + java.math.BigDecimal rating, + String lastName, + String firstName) { + this.passengerId = passengerId; + this.rating = rating; + this.lastName = lastName; + this.firstName = firstName; + } + + @JsonProperty(\\"passenger_id\\") + private Integer passengerId; + private java.math.BigDecimal rating; + @JsonProperty(\\"last_name\\") + private String lastName; + @JsonProperty(\\"first_name\\") + private String firstName; + public Integer getPassengerId() { + return passengerId; + } + + public Passenger setPassengerId(Integer passengerId) { + this.passengerId = passengerId; + return this; + } + + + public java.math.BigDecimal getRating() { + return rating; + } + + public Passenger setRating(java.math.BigDecimal rating) { + this.rating = rating; + return this; + } + + + public String getLastName() { + return lastName; + } + + public Passenger setLastName(String lastName) { + this.lastName = lastName; + return this; + } + + + public String getFirstName() { + return firstName; + } + + public Passenger setFirstName(String firstName) { + this.firstName = firstName; + return this; + } + + public String toString() { + return \\"Passenger [\\" + + \\" passengerId: \\" + passengerId + + \\" rating: \\" + rating + + \\" lastName: \\" + lastName + + \\" firstName: \\" + firstName + + \\" ]\\"; + } + } + + public java.math.BigDecimal getMeterIncrement() { + return meterIncrement; + } + + public RideUpdated1 setMeterIncrement(java.math.BigDecimal meterIncrement) { + this.meterIncrement = meterIncrement; + return this; + } + + + public java.math.BigDecimal getLongitude() { + return longitude; + } + + public RideUpdated1 setLongitude(java.math.BigDecimal longitude) { + this.longitude = longitude; + return this; + } + + + public String getTimestamp() { + return timestamp; + } + + public RideUpdated1 setTimestamp(String timestamp) { + this.timestamp = timestamp; + return this; + } + + + public java.math.BigDecimal getMeterReading() { + return meterReading; + } + + public RideUpdated1 setMeterReading(java.math.BigDecimal meterReading) { + this.meterReading = meterReading; + return this; + } + + + public RideStatus getRideStatus() { + return rideStatus; + } + + public RideUpdated1 setRideStatus(RideStatus rideStatus) { + this.rideStatus = rideStatus; + return this; + } + + + public static enum RideStatus { accepted,pickup,enroute,dropoff } public String toString() { + return \\"RideUpdated1 [\\" + + \\" rideId: \\" + rideId + + \\" heading: \\" + heading + + \\" latitude: \\" + latitude + + \\" passengerCount: \\" + passengerCount + + \\" pointIdx: \\" + pointIdx + + \\" informationSource: \\" + informationSource + + \\" speed: \\" + speed + + \\" driver: \\" + driver + + \\" passenger: \\" + passenger + + \\" meterIncrement: \\" + meterIncrement + + \\" longitude: \\" + longitude + + \\" timestamp: \\" + timestamp + + \\" meterReading: \\" + meterReading + + \\" rideStatus: \\" + rideStatus + + \\" ]\\"; + } +} " `; diff --git a/test/integration.test.js b/test/integration.test.js index 9b7bd20c..42728cbf 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -166,16 +166,6 @@ describe('template integration tests using the generator', () => { await assertExpectedFiles(validatedFiles); }); - it('should generate code using schemas that have $id set', async () => { - await generate('mocks/using-$id-field.yaml'); - - const validatedFiles = [ - 'src/main/java/Application.java', - 'src/main/java/DefaultMessageSchema.java' - ]; - await assertExpectedFiles(validatedFiles); - }); - it('should package and import schemas in another avro namespace', async () => { await generate('mocks/avro-schema-namespace.yaml'); @@ -215,4 +205,39 @@ describe('template integration tests using the generator', () => { ]; await assertExpectedFiles(validatedFiles); }); + + it('should generate a class for a schema property that is an array of objects', async () => { + // Tests that a schema with the items keyword correctly maps the name of the parent to the content within the items + // and the anonymous schema within items doesnt have a class name derived from it. + await generate('mocks/schema-with-array-of-objects.yaml'); + + const validatedFiles = [ + 'src/main/java/Application.java', + 'src/main/java/ChargeAdjustments.java', + 'src/main/java/RideReceipt.java', + 'src/main/java/TestObject.java' + ]; + await assertExpectedFiles(validatedFiles); + }); + + it('should generate one class for a schema with multiple references to it in the asyncapi document', async () => { + /* + For this test, there's duplicate schemas in the asyncapi document. + Calling allSchemas() yeilds unique results (deduplicated) based on either $id or x-parser-schema-id in that order. + The $id needs to be changed because the generator will write file names and such based on it which will always be faulty for this code generator. + Changing the $id of one schema will change the $id only for the one instance, leaving the duplicates behind with the $id they've always had. + This means if we started with 10 schemas, 5 being duplicates with one other schema (15 total; 10 unique), we would end up with 15 unique and 15 total if we changed the schema's $id. + This test ensures all schemas and their duplicates have their $ids renamed to generate the correct file name among other things. + */ + await generate('mocks/schemas-with-duplicate-$ids.yaml'); + + const validatedFiles = [ + 'src/main/java/Application.java', + 'src/main/java/Driver.java', + 'src/main/java/Passenger.java', + 'src/main/java/PaymentCharged.java', + 'src/main/java/RideUpdated1.java' + ]; + await assertExpectedFiles(validatedFiles); + }); }); diff --git a/test/mocks/schema-with-array-of-objects.yaml b/test/mocks/schema-with-array-of-objects.yaml new file mode 100644 index 00000000..2e9cc758 --- /dev/null +++ b/test/mocks/schema-with-array-of-objects.yaml @@ -0,0 +1,167 @@ +components: + schemas: + RideReceipt: + $schema: 'http://json-schema.org/draft-07/schema#' + type: object + title: The Root Schema + definitions: {} + required: + - request_id + - subtotal + - total_charged + - total_owed + - total_fare + - currency_code + - charge_adjustments + - duration + - distance + - distance_label + properties: + total_owed: + default: '' + examples: + - $12.78 + type: string + title: The Total_owed Schema + $id: '#/properties/total_owed' + duration: + default: '' + examples: + - '00:11:35' + pattern: ^(.*)$ + type: string + title: The Duration Schema + $id: '#/properties/duration' + test_object: + title: The test schema + $id: '#/properties/test_object' + type: object + properties: + field1: + default: '' + examples: + - $12.78 + type: string + title: field1 schema + $id: '#/properties/test_object/properties/field1' + charge_adjustments: + default: [] + examples: + - - amount: '-2.43' + name: Promotion + type: promotion + - amount: '1.00' + name: Booking Fee + type: booking_fee + - amount: '0.78' + name: Rounding Down + type: rounding_down + additionalItems: true + description: An explanation about the purpose of this instance. + type: array + title: The Charge_adjustments Schema + items: + default: {} + examples: + - amount: '-2.43' + name: Promotion + type: promotion + - amount: '1.00' + name: Booking Fee + type: booking_fee + - amount: '0.78' + name: Rounding Down + type: rounding_down + description: An explanation about the purpose of this instance. + type: object + title: The Items Schema + required: + - name + - amount + - type + properties: + amount: + default: '' + examples: + - '-2.43' + description: An explanation about the purpose of this instance. + type: string + title: The Amount Schema + $id: '#/properties/charge_adjustments/items/properties/amount' + name: + default: '' + examples: + - Promotion + description: An explanation about the purpose of this instance. + type: string + title: The Name Schema + $id: '#/properties/charge_adjustments/items/properties/name' + type: + default: '' + examples: + - promotion + description: An explanation about the purpose of this instance. + type: string + title: The Type Schema + $id: '#/properties/charge_adjustments/items/properties/type' + $id: '#/properties/charge_adjustments/items' + $id: '#/properties/charge_adjustments' + currency_code: + default: '' + examples: + - USD + pattern: ^(.*)$ + type: string + title: The Currency_code Schema + $id: '#/properties/currency_code' + $id: 'http://example.com/root.json' + messages: + Billing Receipt Created: + payload: + $ref: '#/components/schemas/RideReceipt' + description: >- + This event is generated when a trip is completed and the credit charge + has occurred. + schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0 + contentType: application/json +channels: + 'acme/rideshare/billing/receipt/created/0.0.1/{region}/chargify/{ride_id}': + subscribe: + bindings: + solace: + bindingVersion: 0.1.0 + destinations: + - destinationType: topic + message: + $ref: '#/components/messages/Billing Receipt Created' + parameters: + ride_id: + schema: + type: string + region: + schema: + type: string + enum: + - US + - UK + - CA + - MX +asyncapi: 2.0.0 +info: + description: >- + Simplify expense, travel, and invoice management with SAP Concur partner + integrations + + + Our open platform makes it possible for partners to develop apps and + services that easily integrate with SAP Concur solutions and extend the + value of our products. With our partner apps you can: + + + * Use data to make more-informed business decisions + + * Reduce costs, improve compliance, and increase efficiency + + * Give employees a better, smoother travel experience + title: ExpenseReportingIntegrationApplication + version: 0.0.1 diff --git a/test/mocks/schemas-with-duplicate-$ids.yaml b/test/mocks/schemas-with-duplicate-$ids.yaml new file mode 100644 index 00000000..646d0227 --- /dev/null +++ b/test/mocks/schemas-with-duplicate-$ids.yaml @@ -0,0 +1,530 @@ +components: + schemas: + PaymentCharged: + default: {} + $schema: 'http://json-schema.org/draft-07/schema' + examples: + - ride_id: 2345234 + entity_type: Driver + amount_charged: 12.32 + driver: + driver_id: 1234132 + rating: 4 + last_name: Smith + car_class: SUV + first_name: Frank + payment_charged_id: '23232323' + passenger: + passenger_id: 2345243 + rating: 2 + last_name: Menning + first_name: Jesse + payment_status: accepted + invoice_system_id: PSG-32923 + information_source: ProcessPayment + timestamp: '2020-06-03T16:51:47.29612-04:00' + description: The root schema comprises the entire JSON document. + additionalProperties: true + type: object + title: The root schema + required: + - payment_charged_id + - timestamp + - information_source + - payment_status + - invoice_system_id + - amount_charged + - ride_id + - entity_type + - driver + - passenger + properties: + ride_id: + default: 0 + examples: + - 2345234 + description: An explanation about the purpose of this instance. + type: integer + title: The ride_id schema + $id: '#/properties/ride_id' + entity_type: + default: '' + examples: + - Driver + description: An explanation about the purpose of this instance. + type: string + title: The entity_type schema + $id: '#/properties/entity_type' + amount_charged: + default: 0 + examples: + - 12.32 + description: An explanation about the purpose of this instance. + type: number + title: The amount_charged schema + $id: '#/properties/amount_charged' + driver: + default: {} + examples: + - driver_id: 1234132 + rating: 4 + last_name: Smith + car_class: SUV + first_name: Frank + description: An explanation about the purpose of this instance. + additionalProperties: true + type: object + title: The driver schema + required: + - driver_id + - first_name + - last_name + - rating + - car_class + properties: + driver_id: + default: 0 + examples: + - 1234132 + description: An explanation about the purpose of this instance. + type: integer + title: The driver_id schema + $id: '#/properties/driver/properties/driver_id' + rating: + default: 0 + examples: + - 4 + description: An explanation about the purpose of this instance. + type: integer + title: The rating schema + $id: '#/properties/driver/properties/rating' + last_name: + default: '' + examples: + - Smith + description: An explanation about the purpose of this instance. + type: string + title: The last_name schema + $id: '#/properties/driver/properties/last_name' + car_class: + default: '' + examples: + - SUV + description: An explanation about the purpose of this instance. + type: string + title: The car_class schema + $id: '#/properties/driver/properties/car_class' + first_name: + default: '' + examples: + - Frank + description: An explanation about the purpose of this instance. + type: string + title: The first_name schema + $id: '#/properties/driver/properties/first_name' + $id: '#/properties/driver' + payment_charged_id: + default: '' + examples: + - '23232323' + description: An explanation about the purpose of this instance. + type: string + title: The payment_charged_id schema + $id: '#/properties/payment_charged_id' + passenger: + default: {} + examples: + - passenger_id: 2345243 + rating: 2 + last_name: Menning + first_name: Jesse + description: An explanation about the purpose of this instance. + additionalProperties: true + type: object + title: The passenger schema + required: + - passenger_id + - first_name + - last_name + - rating + properties: + passenger_id: + default: 0 + examples: + - 2345243 + description: An explanation about the purpose of this instance. + type: integer + title: The passenger_id schema + $id: '#/properties/passenger/properties/passenger_id' + rating: + default: 0 + examples: + - 2 + description: An explanation about the purpose of this instance. + type: integer + title: The rating schema + $id: '#/properties/passenger/properties/rating' + last_name: + default: '' + examples: + - Menning + description: An explanation about the purpose of this instance. + type: string + title: The last_name schema + $id: '#/properties/passenger/properties/last_name' + first_name: + default: '' + examples: + - Jesse + description: An explanation about the purpose of this instance. + type: string + title: The first_name schema + $id: '#/properties/passenger/properties/first_name' + $id: '#/properties/passenger' + payment_status: + default: '' + examples: + - accepted + description: An explanation about the purpose of this instance. + type: string + title: The payment_status schema + $id: '#/properties/payment_status' + invoice_system_id: + default: '' + examples: + - PSG-32923 + description: An explanation about the purpose of this instance. + type: string + title: The invoice_system_id schema + $id: '#/properties/invoice_system_id' + information_source: + default: '' + examples: + - ProcessPayment + description: An explanation about the purpose of this instance. + type: string + title: The information_source schema + $id: '#/properties/information_source' + timestamp: + default: '' + examples: + - '2020-06-03T16:51:47.29612-04:00' + description: An explanation about the purpose of this instance. + type: string + title: The timestamp schema + $id: '#/properties/timestamp' + $id: 'http://example.com/example.json' + RideUpdated-1: + default: {} + $schema: 'http://json-schema.org/draft-07/schema' + examples: + - ride_id: 545496c5-a334-4344-9662-efde68c0b98a + heading: 111 + latitude: 40.75473 + passenger_count: 1 + point_idx: 107 + information_source: RideDispatcher + speed: 8 + driver: + driver_id: 1234132 + rating: 4.75 + last_name: Smith + car_class: SUV + first_name: Frank + passenger: + passenger_id: 2345243 + rating: 2.23 + last_name: Menning + first_name: Tamimi + meter_increment: 0.02278058 + longitude: -73.98385 + timestamp: '2020-06-03T16:51:47.292-04:00' + meter_reading: 2.4375222 + ride_status: enroute + description: The root schema comprises the entire JSON document. + additionalProperties: true + type: object + title: The root schema + properties: + ride_id: + default: '' + examples: + - 545496c5-a334-4344-9662-efde68c0b98a + description: A UUID identifying the ride. + type: string + title: The ride identifier + $id: '#/properties/ride_id' + heading: + default: 0 + examples: + - 111 + maximum: 359 + description: 0-359 degrees approximate heading of the vehicle. + type: integer + title: The heading schema + minimum: 0 + $id: '#/properties/heading' + latitude: + default: 0 + examples: + - -40.75473 + maximum: 90 + description: Current latitude of the vehicle. + type: number + title: The latitude schema + minimum: -90 + $id: '#/properties/latitude' + passenger_count: + default: 0 + examples: + - 1 + description: The number of passengers in the car during this ride. + type: integer + title: The passenger_count schema + minimum: 0 + $id: '#/properties/passenger_count' + point_idx: + default: 0 + examples: + - 107 + description: >- + The update number for the ride. This increments for each RideUpdate + for a given ride. + type: integer + title: The point_idx schema + $id: '#/properties/point_idx' + information_source: + default: '' + examples: + - RideDispatcher + description: The app that sent this event. + type: string + title: The information_source schema + $id: '#/properties/information_source' + speed: + default: 0 + examples: + - 20 + description: Speed of the taxi in unknown units. + type: integer + title: The speed schema + minimum: 0 + $id: '#/properties/speed' + driver: + default: {} + examples: + - driver_id: 1234132 + rating: 4.73 + last_name: Smith + car_class: SUV + first_name: Frank + description: Information about the driver. + additionalProperties: true + type: object + title: The driver schema + required: + - driver_id + - first_name + - last_name + - rating + - car_class + properties: + driver_id: + default: 0 + examples: + - 1234132 + description: A unique ID for the driver. + type: integer + title: The driver_id schema + $id: '#/properties/driver/properties/driver_id' + rating: + default: 0 + examples: + - 4.32 + maximum: 5 + description: >- + The driver's current 5-star rating, showing 2 decimal places of + accuracy. + type: number + title: The rating schema + minimum: 0 + $id: '#/properties/driver/properties/rating' + last_name: + default: '' + examples: + - Smith + description: The Driver's Last Name. + type: string + title: The last_name schema + $id: '#/properties/driver/properties/last_name' + car_class: + default: '' + examples: + - SUV + - Minivan + - Sedan + - Coupe + description: The class of the vehicle. + type: string + title: The car_class schema + $id: '#/properties/driver/properties/car_class' + first_name: + default: '' + examples: + - Frank + description: The Driver's first name. + type: string + title: The first_name schema + $id: '#/properties/driver/properties/first_name' + $id: '#/properties/driver' + passenger: + default: {} + examples: + - passenger_id: 2345243 + rating: 2.25 + last_name: Menning + first_name: Tamimi + description: Information about the Passenger. + additionalProperties: true + type: object + title: The passenger schema + required: + - passenger_id + - first_name + - last_name + - rating + properties: + passenger_id: + default: 0 + examples: + - 2345243 + description: A unique ID for the passenger. + type: integer + title: The passenger_id schema + $id: '#/properties/passenger/properties/passenger_id' + rating: + default: 0 + examples: + - 2.25 + maximum: 5 + description: >- + The passenger's current 5-star rating, showing 2 decimal places + of accuracy. + type: number + title: The rating schema + minimum: 0 + $id: '#/properties/passenger/properties/rating' + last_name: + default: '' + examples: + - Menning + description: The passenger's last name. + type: string + title: The last_name schema + $id: '#/properties/passenger/properties/last_name' + first_name: + default: '' + examples: + - Jesse + description: The passenger's first name. + type: string + title: The first_name schema + $id: '#/properties/passenger/properties/first_name' + $id: '#/properties/passenger' + meter_increment: + default: 0 + examples: + - 0.02278058 + description: The meter increment rate. + type: number + title: The meter_increment schema + $id: '#/properties/meter_increment' + longitude: + default: 0 + examples: + - -123.98385 + maximum: 180 + description: Current longitude of the vehicle. + type: number + title: The longitude schema + minimum: -180 + $id: '#/properties/longitude' + timestamp: + default: '' + examples: + - '2020-06-03T16:51:47.292-04:00' + description: The time the RideUpdate is being sent. + type: string + title: The timestamp schema + $id: '#/properties/timestamp' + meter_reading: + default: 0 + examples: + - 2.42 + description: >- + The current value of the taxi's meter, in dollars $. Float value + will always be shown with 2 decimal places (cents). + type: number + title: The meter_reading schema + minimum: 0 + $id: '#/properties/meter_reading' + ride_status: + default: '' + examples: + - enroute + description: The current status of the ride. + type: string + title: The ride_status schema + enum: + - accepted + - pickup + - enroute + - dropoff + $id: '#/properties/ride_status' + $id: 'http://example.com/example.json' + messages: + RideUpdated: + payload: + $ref: '#/components/schemas/RideUpdated-1' + schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0 + contentType: application/json + PaymentCharged: + payload: + $ref: '#/components/schemas/PaymentCharged' + description: '' + schemaFormat: application/vnd.aai.asyncapi+json;version=2.0.0 + contentType: application/json +channels: + 'taxinyc/backoffice/payment/charged/v1/{payment_status}/{driver_id}/{passenger_id}': + subscribe: + message: + $ref: '#/components/messages/PaymentCharged' + parameters: + driver_id: + schema: + type: string + payment_status: + schema: + type: string + passenger_id: + schema: + type: string + 'taxinyc/ops/ride/updated/v1/{ride_status}/{driver_id}/{passenger_id}': + publish: + message: + $ref: '#/components/messages/RideUpdated' + parameters: + driver_id: + schema: + type: string + passenger_id: + schema: + type: string + ride_status: + schema: + type: string +asyncapi: 2.0.0 +info: + description: '' + title: ProcessPayment + version: 0.0.1 diff --git a/test/mocks/using-$id-field.yaml b/test/mocks/using-$id-field.yaml deleted file mode 100644 index 112c31a9..00000000 --- a/test/mocks/using-$id-field.yaml +++ /dev/null @@ -1,86 +0,0 @@ ---- -components: - schemas: - default message schema: - default: {} - $schema: "http://json-schema.org/draft-07/schema" - $id: "http://example.com/example.json" - examples: - - avg_meter_reading: 21.615217 - window_duration_sec: 300 - avg_passenger_count: 1.5 - window_ride_count: 5 - timestamp: "2020-06-04T20:09:59.99832-04:00" - description: "default placeholder for schema" - additionalProperties: true - type: "object" - title: "The root schema" - required: - - "timestamp" - - "avg_meter_reading" - - "avg_passenger_count" - - "window_duration_sec" - - "window_ride_count" - properties: - avg_meter_reading: - default: 0 - examples: - - 21.615217 - description: "An explanation about the purpose of this instance." - type: "number" - title: "The avg_meter_reading schema" - $id: "#/properties/avg_meter_reading" - window_duration_sec: - default: 0 - examples: - - 300 - description: "An explanation about the purpose of this instance." - type: "integer" - title: "The window_duration_sec schema" - $id: "#/properties/window_duration_sec" - avg_passenger_count: - default: 0 - examples: - - 1.5 - description: "An explanation about the purpose of this instance." - type: "number" - title: "The avg_passenger_count schema" - $id: "#/properties/avg_passenger_count" - window_ride_count: - default: 0 - examples: - - 5 - description: "An explanation about the purpose of this instance." - type: "integer" - title: "The window_ride_count schema" - $id: "#/properties/window_ride_count" - timestamp: - default: "" - examples: - - "2020-06-04T20:09:59.99832-04:00" - description: "An explanation about the purpose of this instance." - type: "string" - title: "The timestamp schema" - $id: "#/properties/timestamp" - messages: - ride requested 2: - payload: - $ref: "#/components/schemas/default message schema" - schemaFormat: "application/vnd.aai.asyncapi+json;version=2.0.0" - contentType: "application/json" -servers: - production: - protocol: "smf" - url: "my_server" -channels: - acme/rideshare/ride/requested/0.0.1: - publish: - message: - $ref: "#/components/messages/ride requested 2" -asyncapi: "2.0.0" -info: - x-generated-time: "2021-09-29 13:44 UTC" - description: "test\n\n---\n\ntest" - title: "mh acme 2" - x-view: "provider" - version: "1"