Skip to content

Commit

Permalink
Adding basic schema generation for 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
rcooper-kr committed Aug 28, 2024
1 parent f096022 commit e3a0c61
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 16 deletions.
19 changes: 15 additions & 4 deletions gen/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,26 @@
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<sourceDirectory>${basedir}/src/main/spec/2.6.0</sourceDirectory>
<targetPackage>com.thoughtworks.asyncapi.spec.v2_6_0</targetPackage>
</configuration>
<executions>
<execution>
<id>2.6.0</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<sourceDirectory>${basedir}/src/main/spec/2.6.0</sourceDirectory>
<targetPackage>com.thoughtworks.asyncapi.spec.v2_6_0</targetPackage>
</configuration>
</execution>
<execution>
<id>3.0.0</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<sourceDirectory>${basedir}/src/main/spec/3.0.0</sourceDirectory>
<targetPackage>com.thoughtworks.asyncapi.spec.v3_0_0</targetPackage>
</configuration>
</execution>
</executions>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import com.squareup.javapoet.TypeSpec;
import com.thoughtworks.asyncapi.codegen.Generator;
import com.thoughtworks.asyncapi.mqtt.BaseMqttApi;
import com.thoughtworks.asyncapi.mqtt.SerializerFactory;
import com.thoughtworks.asyncapi.serde.SerializerFactory;
import com.thoughtworks.asyncapi.spec.v2_6_0.AsyncAPI;
import com.thoughtworks.asyncapi.spec.v2_6_0.Operation;
import com.thoughtworks.asyncapi.spec.v2_6_0.OperationTrait;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.thoughtworks.asyncapi.codegen.v3_0_0;

public class AmqpClientGenerator {
}
28 changes: 25 additions & 3 deletions gen/src/main/java/com/thoughtworks/asyncapi/engine/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@SuppressWarnings({"SwitchStatementWithTooFewBranches", "unchecked"})
public class Engine {
Expand Down Expand Up @@ -56,19 +57,40 @@ public void run(File source, File output, String packageName, JsonGenerationConf
var protocols = servers.values().stream().map(m -> (Map<String, Object>) m).map(m -> m.get("protocol")).map(Objects::toString).toList();

switch (version) {
case "3.0.0" -> {
var schema3 = yamlMapper.readValue(source, com.thoughtworks.asyncapi.spec.v3_0_0.AsyncAPI.class);
// todo protocol implementation
switch (mimeType) {
case "application/json" -> {
var extractor = new SchemaObjectExtractor(jsonMapper, createTempDirectory());
var payloads = schema3.getComponents().getMessages().getAdditionalProperties()
.entrySet()
.stream()
.map(e-> {
var message = (Map<String, Object>) e.getValue();
return Map.entry( e.getKey(), message.get("payload"));
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
var resolved = extractor.resolveAllOfInTheBaseTypes(source.toURI(), schema3, payloads);
extractor.extract(resolved);
extractor.render(jsonGenerationConfig);
}
default -> throw new IllegalArgumentException("Unsupported mime type: " + mimeType);
}
}
case "2.6.0" -> {
var schema = yamlMapper.readValue(source, com.thoughtworks.asyncapi.spec.v2_6_0.AsyncAPI.class);
var schema2 = yamlMapper.readValue(source, com.thoughtworks.asyncapi.spec.v2_6_0.AsyncAPI.class);
protocols.forEach(proto -> {
switch (proto) {
case "mqtt" ->
generators.add(new com.thoughtworks.asyncapi.codegen.v2_6_0.MqttClientGenerator(source.toURI(), schema, packageName, output));
generators.add(new com.thoughtworks.asyncapi.codegen.v2_6_0.MqttClientGenerator(source.toURI(), schema2, packageName, output));
default -> throw new IllegalArgumentException("Unsupported protocol: " + proto);
}
});
switch (mimeType) {
case "application/json" -> {
var extractor = new SchemaObjectExtractor(jsonMapper, createTempDirectory());
var resolved = extractor.resolveAllOfInTheBaseTypes(source.toURI(), schema, schema.getComponents().getSchemas().getAdditionalProperties());
var resolved = extractor.resolveAllOfInTheBaseTypes(source.toURI(), schema2, schema2.getComponents().getSchemas().getAdditionalProperties());
extractor.extract(resolved);
extractor.render(jsonGenerationConfig);

Expand Down
10 changes: 10 additions & 0 deletions gen/src/test/java/com/thoughtworks/asyncapi/engine/EngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public static void teardown() {
mqttServer.stopServer();
}

@Test
void testGenerate() throws Exception {
Engine engine = new Engine();
var target = new File("target/EngineTest3");
target.mkdir();
var config = new JsonGenerationConfig();
config.setGenerateBuilders(true);
engine.run(new File("src/test/resources/schema3.yaml"), target, "com.kroger.apis.compliance", config);
}

@Test
void testGenerateAndRun() throws Exception {
Engine engine = new Engine();
Expand Down
4 changes: 2 additions & 2 deletions gen/src/test/resources/Test.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package enginetest;

import com.google.common.util.concurrent.Uninterruptibles;
import com.thoughtworks.asyncapi.mqtt.SerializerFactory;
import com.thoughtworks.asyncapi.mqtt.impl.JacksonSerDe;
import com.thoughtworks.asyncapi.serde.SerializerFactory;
import com.thoughtworks.asyncapi.serde.impl.JacksonSerDe;
import enginetest.model.OrderDetails;
import enginetest.model.PreInquiryRequest;
import org.eclipse.paho.client.mqttv3.IMqttClient;
Expand Down
234 changes: 234 additions & 0 deletions gen/src/test/resources/schema3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
asyncapi: 3.0.0
info:
title: Sales Compliance Service
version: 1.0.0
description: test
The Sales Compliance service exists to ensure Kroger remains in compliance with government regulations specific data must be captured and stored based on certain sales transactions.

defaultContentType: application/json

servers:
dev/qa:
$ref: '#/components/servers/dev~1qa'

channels:
piaRequest:
$ref: '#/components/channels/piaRequest'
piaReply:
$ref: '#/components/channels/piaReply'
transactionRequest:
$ref: '#/components/channels/transactionRequest'

operations:
compliance/pia:
$ref: '#/components/operations/compliance~1pia'
compliance/transaction:
$ref: '#/components/operations/compliance~1transaction'

components:
servers:
dev/qa:
host: 'rabbitmq:5672'
protocol: amqp
security:
- $ref: '#/components/securitySchemes/devQaScheme'
description: test
For development, uses the existing RabbitMQ in the ngpost-rabbit namespace of the aks-ax-shared-01-dev-eastus2 K8S cluster. Differentiate between DEV and QA by the virtual host (rabbitmq-ngpost-dev or rabbitmq-ngpost-qa). All messages should use the Sales-Compliance exchange, and each routing key is bound to a queue of the same name.

This will eventually be migrated to a separate, dedicated RabbitMQ instance for Sales Compliance that is supposed to be located on the Edge server in each store.

securitySchemes:
devQaScheme:
type: userPassword

channelBindings:
amqpBindings:
amqp:
is: routingKey
exchange:
name: Sales-Compliance
type: topic
durable: true
autoDelete: false
vhost: rabbitmq-ngpost-dev OR rabbitmq-ngpost-qa
bindingVersion: 0.3.0

channels:
piaRequest:
address: compliance/pia
messages:
piaRequest:
$ref: '#/components/messages/piaRequest'
bindings:
$ref: '#/components/channelBindings/amqpBindings'
piaReply:
address: null
messages:
piaReply:
$ref: '#/components/messages/piaReply'
transactionRequest:
address: compliance/transaction
messages:
piaRequest:
$ref: '#/components/messages/transactionRequest'
bindings:
$ref: '#/components/channelBindings/amqpBindings'

operations:
compliance/pia:
description: test
action: send
channel:
$ref: '#/channels/piaRequest'
reply:
address:
description: test
location: "$message.header#/reply-to"
channel:
$ref: '#/channels/piaReply'

compliance/transaction:
description: test
action: send
channel:
$ref: '#/channels/transactionRequest'

messages:
piaRequest:
headers:
type: object
properties:
reply-to:
type: string
description: test
payload:
type: object
additionalProperties: false
required:
- transaction
- encryptedCustId
- encryptedIdType
- encryptedIdExpiration
- encryptedDOB
- encryptedLastName
- encryptedFirstName
- encryptedStreet
- encryptedCity
- encryptedState
- encryptedZip
- encryptedSSN
properties:
transaction:
type: string
description: test
encryptedCustId:
type: string
description: test
encryptedIdType:
type: string
description: test
encryptedIdExpiration:
type: string
description: test
encryptedDOB:
type: string
description: test
encryptedLastName:
type: string
description: test
encryptedFirstName:
type: string
description: test
encryptedStreet:
type: string
description: test
encryptedCity:
type: string
description: test
encryptedState:
type: string
description: test
encryptedZip:
type: string
description: test
encryptedSSN:
type: string
description: test

piaReply:
payload:
type: object
additionalProperties: false
required: ["ref", "transaction"]
properties:
ref:
type: string
description: test
transaction:
type: string
description: test

transactionRequest:
payload:
type: object
additionalProperties: false
required:
- timestamp
- salesComplianceRefId
- storeNumber
- divisionNumber
- terminalId
- operatorId
- tenderTypes
- prepaidCards
properties:
timestamp:
type: string
description: test
salesComplianceRefId:
type: string
description: test
storeNumber:
type: string
description: test
divisionNumber:
type: string
description: test
terminalId:
type: string
description: test
operatorId:
type: string
description: test
loyaltyNumber:
type: string
description: test
tenderTypes:
type: array
items:
type: string
pattern: '^\d\d$'
description: test
prepaidCards:
type: array
items:
type: object
description: test
properties:
upc:
type: string
description: test
cardPlanId:
type: string
description: test
purchaseAmount:
type: string
pattern: '^\d+\.\d\d$'
description: test
activationAmount:
type: string
pattern: '^\d+\.\d\d$'
description: test
quantity:
type: integer
description: test
5 changes: 5 additions & 0 deletions lib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.19.0</version>
</dependency>


<dependency>
Expand Down
23 changes: 23 additions & 0 deletions lib/src/main/java/com/thoughtworks/asyncapi/amqp/BaseAmqpApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.thoughtworks.asyncapi.amqp;

import com.rabbitmq.client.ConnectionFactory;
import com.thoughtworks.asyncapi.mqtt.BaseMqttApi;
import com.thoughtworks.asyncapi.serde.SerializerFactory;

import java.util.function.Consumer;

public class BaseAmqpApi {

private final ConnectionFactory connectionFactory;
private final String replyQueueName;
private final SerializerFactory serializerFactory;
private Consumer<BaseMqttApi.SubscriptionException> errorHandler;
private final String defaultMimeType;

public BaseAmqpApi(ConnectionFactory connectionFactory, String replyQueueName, SerializerFactory serializerFactory, String defaultMimeType) {
this.connectionFactory = connectionFactory;
this.replyQueueName = replyQueueName;
this.serializerFactory = serializerFactory;
this.defaultMimeType = defaultMimeType;
}
}
Loading

0 comments on commit e3a0c61

Please sign in to comment.