Skip to content

Commit

Permalink
chore: Improved AsyncAPI interface
Browse files Browse the repository at this point in the history
Improved the creation of Messages.

A 'Message' is now an interface that's implemented by
'MessageObject' and 'MessageReference'. This change
allows to properly define a 'Message' and use it in a more
transparent way.

Added also different builders
  • Loading branch information
ctasada committed Dec 28, 2023
1 parent 95d63a9 commit ca8dc52
Show file tree
Hide file tree
Showing 17 changed files with 740 additions and 247 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
@EqualsAndHashCode(callSuper = true)
public class AsyncAPI extends ExtendableObject {

public static final String ASYNCAPI_DEFAULT_VERSION = "3.0.0";

/**
* REQUIRED. Specifies the AsyncAPI Specification version being used. It can be used by tooling Specifications and
* clients to interpret the version. The structure shall be major.minor.patch, where patch versions must be
Expand All @@ -39,7 +41,7 @@ public class AsyncAPI extends ExtendableObject {
@NotNull
@Builder.Default
@JsonProperty(value = "asyncapi")
private String asyncapi = "3.0.0";
private String asyncapi = ASYNCAPI_DEFAULT_VERSION;

/**
* Identifier of the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,122 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExtendableObject;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExternalDocumentation;
import io.github.stavshamir.springwolf.asyncapi.v3.model.Reference;
import io.github.stavshamir.springwolf.asyncapi.v3.model.Tag;
import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.CorrelationID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;

/**
* Describes a message received on a given channel and operation.
* Represents a Message. A Message can be a MessageObject or a MessageReference.
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Message extends ExtendableObject implements Reference {

/**
* Schema definition of the application headers. Schema MUST be a map of key-value pairs. It MUST NOT define the
* protocol headers. If this is a Schema Object, then the schemaFormat will be assumed to be
* "application/vnd.aai.asyncapi+json;version=asyncapi" where the version is equal to the AsyncAPI Version String.
*/
@JsonProperty(value = "headers")
private MessageHeaders headers;

/**
* Definition of the message payload. If this is a Schema Object, then the schemaFormat will be assumed to be
* "application/vnd.aai.asyncapi+json;version=asyncapi" where the version is equal to the AsyncAPI Version String.
*/
@JsonProperty(value = "payload")
private MessagePayload payload;

/**
* Definition of the correlation ID used for message tracing or matching.
*/
@JsonProperty(value = "correlationId")
private CorrelationID correlationId;

/**
* The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type
* (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field.
*/
@JsonProperty(value = "contentType")
private String contentType;

/**
* A machine-friendly name for the message.
*/
@JsonProperty(value = "name")
private String name;

/**
* A human-friendly title for the message.
*/
@JsonProperty(value = "title")
private String title;

/**
* A short summary of what the message is about.
*/
@JsonProperty(value = "summary")
private String summary;

/**
* A verbose explanation of the message. <a href="https://spec.commonmark.org/">CommonMark syntax</a> can be used
* for rich text representation.
*/
@JsonProperty(value = "description")
private String description;

/**
* A list of tags for logical grouping and categorization of messages.
*/
@JsonProperty(value = "tags")
private List<Tag> tags;

/**
* Additional external documentation for this message.
*/
@JsonProperty(value = "externalDocs")
private ExternalDocumentation externalDocs;

/**
* A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message.
*/
@JsonProperty(value = "bindings")
private Map<String, MessageBinding> bindings;

/**
* List of examples.
*/
@JsonProperty(value = "examples")
private List<MessageExample> examples;

/**
* A list of traits to apply to the message object. Traits MUST be merged using traits merge mechanism.
* The resulting object MUST be a valid Message Object.
*/
@JsonProperty(value = "traits")
private List<MessageTrait> traits;

@JsonIgnore
private String ref;

@Override
public String getRef() {
return ref;
}
}
public interface Message {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf.asyncapi.v3.model.channel.message;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.stavshamir.springwolf.asyncapi.v3.bindings.MessageBinding;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExtendableObject;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExternalDocumentation;
import io.github.stavshamir.springwolf.asyncapi.v3.model.Tag;
import io.github.stavshamir.springwolf.asyncapi.v3.model.channel.CorrelationID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;

/**
* Describes a message received on a given channel and operation.
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class MessageObject extends ExtendableObject implements Message {

/**
* The key represents the message identifier. The messageId value is case-sensitive. Tools and libraries MAY use
* the messageId value to uniquely identify a message, therefore, it is RECOMMENDED to follow common programming
* naming conventions.
*/
@JsonIgnore
private String messageId;

/**
* Schema definition of the application headers. Schema MUST be a map of key-value pairs. It MUST NOT define the
* protocol headers. If this is a Schema Object, then the schemaFormat will be assumed to be
* "application/vnd.aai.asyncapi+json;version=asyncapi" where the version is equal to the AsyncAPI Version String.
*/
@JsonProperty(value = "headers")
private MessageHeaders headers;

/**
* Definition of the message payload. If this is a Schema Object, then the schemaFormat will be assumed to be
* "application/vnd.aai.asyncapi+json;version=asyncapi" where the version is equal to the AsyncAPI Version String.
*/
@JsonProperty(value = "payload")
private MessagePayload payload;

/**
* Definition of the correlation ID used for message tracing or matching.
*/
@JsonProperty(value = "correlationId")
private CorrelationID correlationId;

/**
* The content type to use when encoding/decoding a message's payload. The value MUST be a specific media type
* (e.g. application/json). When omitted, the value MUST be the one specified on the defaultContentType field.
*/
@JsonProperty(value = "contentType")
private String contentType;

/**
* A machine-friendly name for the message.
*/
@JsonProperty(value = "name")
private String name;

/**
* A human-friendly title for the message.
*/
@JsonProperty(value = "title")
private String title;

/**
* A short summary of what the message is about.
*/
@JsonProperty(value = "summary")
private String summary;

/**
* A verbose explanation of the message. <a href="https://spec.commonmark.org/">CommonMark syntax</a> can be used
* for rich text representation.
*/
@JsonProperty(value = "description")
private String description;

/**
* A list of tags for logical grouping and categorization of messages.
*/
@JsonProperty(value = "tags")
private List<Tag> tags;

/**
* Additional external documentation for this message.
*/
@JsonProperty(value = "externalDocs")
private ExternalDocumentation externalDocs;

/**
* A map where the keys describe the name of the protocol and the values describe protocol-specific definitions for the message.
*/
@JsonProperty(value = "bindings")
private Map<String, MessageBinding> bindings;

/**
* List of examples.
*/
@JsonProperty(value = "examples")
private List<MessageExample> examples;

/**
* A list of traits to apply to the message object. Traits MUST be merged using traits merge mechanism.
* The resulting object MUST be a valid Message Object.
*/
@JsonProperty(value = "traits")
private List<MessageTrait> traits;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,43 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.github.stavshamir.springwolf.asyncapi.v3.model.Reference;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class MessageReference implements Reference {
public class MessageReference implements Message, Reference {

@EqualsAndHashCode.Include
@ToString.Include
@JsonIgnore
private String ref;

@Override
public String getRef() {
return ref;
}

/**
* Convenient Builder to create a Message reference to an existing Message
* @param message Message to create the reference to. This Message MUST have a 'messageId' field
* @return a Message with the 'ref' field pointing to "#/components/messages/{messageId"
*/
public static MessageReference fromMessage(MessageObject message) {
var messageId = message.getMessageId();
if (messageId == null) {
throw new IllegalArgumentException("The message must have a 'messageId' defined");
}
return new MessageReference("#/components/messages/" + messageId);
}

public static MessageReference fromMessage(String messageName) {
return new MessageReference("#/components/messages/" + messageName);
}

public static MessageReference fromSchema(String schemaName) {
return new MessageReference("#/components/schemas/" + schemaName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.stavshamir.springwolf.asyncapi.v3.model.ExtendableObject;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand Down Expand Up @@ -35,8 +36,10 @@ public class MultiFormatSchema extends ExtendableObject {
* When using Reference Objects within the schema, the schemaFormat of the referenced resource MUST match the
* schemaFormat of the schema containing the reference.
*/
@Builder.Default
@NotNull
@JsonProperty(value = "schemaFormat")
private String schemaFormat;
private String schemaFormat = SchemaFormat.DEFAULT.toString();

/**
* Required. Definition of the message payload. It can be of any type but defaults to Schema Object. It MUST match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ public class Schema extends ExtendableObject implements Reference {
@JsonProperty("enum")
private List<String> enumValues;

@JsonProperty(value = "examples")
public List<Object> examples;

@JsonProperty(value = "additionalProperties")
public Schema additionalProperties;

@JsonProperty(value = "required")
public List<String> required;

@JsonProperty(value = "allOf")
public List<Schema> allOf;

@JsonProperty(value = "oneOf")
public List<Schema> oneOf;

@JsonProperty(value = "anyOf")
public List<Schema> anyOf;

@JsonProperty(value = "const")
public Object constValue;

@JsonIgnore
private String ref;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf.asyncapi.v3.model.schema;

import static io.github.stavshamir.springwolf.asyncapi.v3.model.AsyncAPI.ASYNCAPI_DEFAULT_VERSION;

public enum SchemaFormat {
/**
* This is the default when a schemaFormat is not provided.
*/
DEFAULT("application/vnd.aai.asyncapi+json;version=" + ASYNCAPI_DEFAULT_VERSION),
ASYNCAPI_V3("application/vnd.aai.asyncapi;version=" + ASYNCAPI_DEFAULT_VERSION),
ASYNCAPI_V3_JSON("application/vnd.aai.asyncapi+json;version=" + ASYNCAPI_DEFAULT_VERSION),
ASYNCAPI_V3_YAML("application/vnd.aai.asyncapi+yaml;version=" + ASYNCAPI_DEFAULT_VERSION),
JSON_SCHEMA_JSON("application/schema+json;version=draft-07"),
JSON_SCHEMA_YAML("application/schema+yaml;version=draft-07"),
AVRO_V1_9_0("application/vnd.apache.avro;version=1.9.0"),
RAML_V1("application/raml+yaml;version=1.0"),
PROTOBUF_V2("application/vnd.google.protobuf;version=2"),
PROTOBUF_V3("application/vnd.google.protobuf;version=3");

public final String value;

private SchemaFormat(String schemaFormat) {
this.value = schemaFormat;
}

@Override
public String toString() {
return this.value;
}
}
Loading

0 comments on commit ca8dc52

Please sign in to comment.