Skip to content

Commit

Permalink
W-12689952: add ibmmq message binding in async21+
Browse files Browse the repository at this point in the history
- add message binding model, parser and emitter
- add unit validation and cycle tests
- add model to APIEntities and model.md
  • Loading branch information
arielmirra committed Feb 7, 2024
1 parent 36343b6 commit b612202
Show file tree
Hide file tree
Showing 15 changed files with 331 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package amf.apicontract.client.platform.model.domain.bindings.ibmmq

import amf.apicontract.client.platform.model.domain.bindings.{BindingVersion, MessageBinding}
import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{IBMMQMessageBinding => InternalIBMMQMessageBinding}
import amf.apicontract.internal.convert.ApiClientConverters._
import amf.core.client.platform.model
import amf.core.client.platform.model.{IntField, StrField}

import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}

@JSExportAll
case class IBMMQMessageBinding(override private[amf] val _internal: InternalIBMMQMessageBinding)
extends MessageBinding
with BindingVersion {
@JSExportTopLevel("IBMMQMessageBinding")
def this() = this(InternalIBMMQMessageBinding())

def messageType: StrField = _internal.messageType
def headers: StrField = _internal.headers
def description: StrField = _internal.description
def expiry: IntField = _internal.expiry

def withType(messageType: String): this.type = {
_internal.withMessageType(messageType)
this
}

def withHeaders(headers: String): this.type = {
_internal.withHeaders(headers)
this
}

def withDescription(description: String): this.type = {
_internal.withDescription(description)
this
}

def withExpiry(expiry: Int): this.type = {
_internal.withExpiry(expiry)
this
}

override protected def bindingVersion: model.StrField = _internal.bindingVersion

override def withBindingVersion(bindingVersion: String): this.type = {
_internal.withBindingVersion(bindingVersion)
this
}

override def linkCopy(): IBMMQMessageBinding = _internal.linkCopy()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package amf.apicontract.client.scala.model.domain.bindings.ibmmq

import amf.apicontract.client.scala.model.domain.bindings.{BindingVersion, MessageBinding}
import amf.apicontract.internal.metamodel.domain.bindings.IBMMQMessageBindingModel
import amf.apicontract.internal.metamodel.domain.bindings.IBMMQMessageBindingModel._
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.IBMMQ
import amf.core.client.scala.model.{IntField, StrField}
import amf.core.client.scala.model.domain.{DomainElement, Linkable}
import amf.core.internal.metamodel.Field
import amf.core.internal.parser.domain.{Annotations, Fields}
import amf.shapes.client.scala.model.domain.Key

class IBMMQMessageBinding(override val fields: Fields, override val annotations: Annotations)
extends MessageBinding
with BindingVersion
with Key {

override protected def bindingVersionField: Field = BindingVersion
override def meta: IBMMQMessageBindingModel.type = IBMMQMessageBindingModel

def messageType: StrField = fields.field(MessageType)
def headers: StrField = fields.field(Headers)
def description: StrField = fields.field(Description)
def expiry: IntField = fields.field(Expiry)

def withMessageType(messageType: String): this.type = set(MessageType, messageType)
def withHeaders(headers: String): this.type = set(Headers, headers)
def withDescription(description: String): this.type = set(Description, description)
def withExpiry(expiry: Int): this.type = set(Expiry, expiry)

override def key: StrField = fields.field(IBMMQMessageBindingModel.key)

override def componentId: String = s"/$IBMMQ-message"

override def linkCopy(): IBMMQMessageBinding = IBMMQMessageBinding()

override protected def classConstructor: (Fields, Annotations) => Linkable with DomainElement =
IBMMQMessageBinding.apply
}

object IBMMQMessageBinding {

def apply(): IBMMQMessageBinding = apply(Annotations())

def apply(annotations: Annotations): IBMMQMessageBinding = apply(Fields(), annotations)

def apply(fields: Fields, annotations: Annotations): IBMMQMessageBinding =
new IBMMQMessageBinding(fields, annotations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import amf.apicontract.client.scala.model.domain.bindings.amqp.{
Amqp091Queue
}
import amf.apicontract.client.scala.model.domain.bindings.http.{HttpMessageBinding, HttpOperationBinding}
import amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQMessageBinding
import amf.apicontract.client.scala.model.domain.bindings.kafka.{KafkaMessageBinding, KafkaOperationBinding}
import amf.apicontract.client.scala.model.domain.bindings.mqtt.{
MqttMessageBinding,
Expand Down Expand Up @@ -112,6 +113,7 @@ trait ApiBaseConverter
with MqttServerLastWillConverter
with Amqp091ChannelExchangeConverter
with Amqp091QueueConverter
with IBBMQMessageBindingConverter
with ChannelBindingConverter
with OperationBindingConverter
with MessageBindingConverter
Expand Down Expand Up @@ -311,6 +313,15 @@ trait Amqp091QueueConverter extends PlatformSecrets {
}
}

trait IBBMQMessageBindingConverter extends PlatformSecrets {
implicit object IBBMQMessageBindingMatcher
extends BidirectionalMatcher[IBMMQMessageBinding, domain.bindings.ibmmq.IBMMQMessageBinding] {
override def asClient(from: IBMMQMessageBinding): domain.bindings.ibmmq.IBMMQMessageBinding =
platform.wrap[domain.bindings.ibmmq.IBMMQMessageBinding](from)
override def asInternal(from: domain.bindings.ibmmq.IBMMQMessageBinding): IBMMQMessageBinding = from._internal
}
}

trait EndPointConverter extends PlatformSecrets {

implicit object EndPointMatcher extends BidirectionalMatcher[EndPoint, domain.EndPoint] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import amf.apicontract.client.platform.model.domain.api.{AsyncApi, WebApi}
import amf.apicontract.client.platform.model.domain.bindings._
import amf.apicontract.client.platform.model.domain.bindings.amqp._
import amf.apicontract.client.platform.model.domain.bindings.http.{HttpMessageBinding, HttpOperationBinding}
import amf.apicontract.client.platform.model.domain.bindings.ibmmq.IBMMQMessageBinding
import amf.apicontract.client.platform.model.domain.bindings.kafka.{KafkaMessageBinding, KafkaOperationBinding}
import amf.apicontract.client.platform.model.domain.bindings.mqtt.{
MqttMessageBinding,
Expand Down Expand Up @@ -274,6 +275,9 @@ private[amf] object ApiRegister extends UniqueInitializer with PlatformSecrets {
platform.registerWrapper(EmptyBindingModel) {
case s: amf.apicontract.client.scala.model.domain.bindings.EmptyBinding => EmptyBinding(s)
}
platform.registerWrapper(IBMMQMessageBindingModel) {
case s: amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQMessageBinding => IBMMQMessageBinding(s)
}
platform.registerWrapper(APIContractProcessingDataModel) {
case s: amf.apicontract.client.scala.model.document.APIContractProcessingData => APIContractProcessingData(s)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ private[amf] object APIEntities extends Entities {
ParameterKeyMappingModel,
ComponentModuleModel,
ParameterFederationMetadataModel,
EndpointFederationMetadataModel
EndpointFederationMetadataModel,
IBMMQMessageBindingModel
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package amf.apicontract.internal.metamodel.domain.bindings

import amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQMessageBinding
import amf.core.client.scala.model.domain.AmfObject
import amf.core.client.scala.vocabulary.Namespace.ApiBinding
import amf.core.client.scala.vocabulary.ValueType
import amf.core.internal.metamodel.Field
import amf.core.internal.metamodel.Type.{Int, Str}
import amf.core.internal.metamodel.domain.{ModelDoc, ModelVocabularies}

object IBMMQMessageBindingModel extends MessageBindingModel with BindingVersion {
val MessageType: Field =
Field(
Str,
ApiBinding + "messageType",
ModelDoc(ModelVocabularies.ApiBinding, "type", "The type of the message")
)

val Headers: Field =
Field(
Str,
ApiBinding + "headers",
ModelDoc(ModelVocabularies.ApiBinding, "type", "The type of the message")
)

val Description: Field =
Field(
Str,
ApiBinding + "headers",
ModelDoc(ModelVocabularies.ApiBinding, "type", "The type of the message")
)

val Expiry: Field =
Field(
Int,
ApiBinding + "expiry",
ModelDoc(ModelVocabularies.ApiBinding, "type", "The type of the message")
)

override def modelInstance: AmfObject = IBMMQMessageBinding()

override def fields: List[Field] =
List(MessageType, Headers, Description, Expiry, BindingVersion) ++ MessageBindingModel.fields

override val `type`: List[ValueType] = ApiBinding + "IBMMQMessageBinding" :: MessageBindingModel.`type`

override val key: Field = Type

override val doc: ModelDoc = ModelDoc(ModelVocabularies.ApiBinding, "IBMMQMessageBinding")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package amf.apicontract.internal.spec.async.emitters.bindings
import amf.apicontract.client.scala.model.domain.bindings.MessageBinding
import amf.apicontract.client.scala.model.domain.bindings.amqp.Amqp091MessageBinding
import amf.apicontract.client.scala.model.domain.bindings.http.HttpMessageBinding
import amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQMessageBinding
import amf.apicontract.client.scala.model.domain.bindings.kafka.KafkaMessageBinding
import amf.apicontract.client.scala.model.domain.bindings.mqtt.MqttMessageBinding
import amf.apicontract.internal.metamodel.domain.bindings.{
Amqp091MessageBindingModel,
HttpMessageBindingModel,
IBMMQMessageBindingModel,
KafkaMessageBindingModel
}
import amf.apicontract.internal.spec.async.emitters.domain
Expand Down Expand Up @@ -35,6 +37,7 @@ class AsyncApiMessageBindingsEmitter(binding: MessageBinding, ordering: SpecOrde
case binding: HttpMessageBinding => Some(new HttpMessageEmitter(binding, ordering))
case binding: KafkaMessageBinding => Some(new KafkaMessageEmitter(binding, ordering))
case binding: MqttMessageBinding => Some(new MqttMessageEmitter(binding, ordering))
case binding: IBMMQMessageBinding => Some(new IBMMQMessageEmitter(binding, ordering))
case _ => None
}

Expand Down Expand Up @@ -121,3 +124,26 @@ class Amqp091MessageEmitter(binding: Amqp091MessageBinding, ordering: SpecOrderi

override def position(): Position = pos(binding.annotations)
}

class IBMMQMessageEmitter(binding: IBMMQMessageBinding, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends AsyncApiCommonBindingEmitter {
override def emit(b: EntryBuilder): Unit = {
b.entry(
YNode("ibmmq"),
_.obj { emitter =>
val result = ListBuffer[EntryEmitter]()
val fs = binding.fields

fs.entry(IBMMQMessageBindingModel.MessageType).foreach(f => result += ValueEmitter("type", f))
fs.entry(IBMMQMessageBindingModel.Headers).foreach(f => result += ValueEmitter("headers", f))
fs.entry(IBMMQMessageBindingModel.Description).foreach(f => result += ValueEmitter("description", f))
fs.entry(IBMMQMessageBindingModel.Expiry).foreach(f => result += ValueEmitter("expiry", f))
emitBindingVersion(fs, result)
traverse(ordering.sorted(result), emitter)
}
)
}

override def position(): Position = pos(binding.annotations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ package amf.apicontract.internal.spec.async.parser.bindings

import amf.apicontract.client.scala.model.domain.bindings.{MessageBinding, MessageBindings}
import amf.apicontract.internal.metamodel.domain.bindings._
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{Amqp, Http, Kafka, Mqtt}
import amf.apicontract.internal.spec.async.parser.bindings.message.{
Amqp091MessageBindingParser,
HttpMessageBindingParser,
KafkaMessageBindingParser,
MqttMessageBindingParser
}
import amf.apicontract.internal.spec.async.parser.bindings.Bindings._
import amf.apicontract.internal.spec.async.parser.bindings.message._
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.apicontract.internal.spec.common.WebApiDeclarations.ErrorMessageBindings
import amf.apicontract.internal.spec.spec.OasDefinitions
Expand All @@ -22,7 +17,8 @@ object AsyncMessageBindingsParser {
Amqp -> Amqp091MessageBindingParser,
Http -> HttpMessageBindingParser,
Kafka -> KafkaMessageBindingParser,
Mqtt -> MqttMessageBindingParser
Mqtt -> MqttMessageBindingParser,
IBMMQ -> IBMMQMessageBindingParser
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package amf.apicontract.internal.spec.async.parser.bindings.message

import amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQMessageBinding
import amf.apicontract.internal.metamodel.domain.bindings.IBMMQMessageBindingModel
import amf.apicontract.internal.spec.async.parser.bindings.BindingParser
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.core.internal.parser.YMapOps
import amf.core.internal.parser.domain.Annotations
import org.yaml.model.{YMap, YMapEntry}

object IBMMQMessageBindingParser extends BindingParser[IBMMQMessageBinding] {
override def parse(entry: YMapEntry, parent: String)(implicit ctx: AsyncWebApiContext): IBMMQMessageBinding = {
val binding = IBMMQMessageBinding(Annotations(entry))
val map = entry.value.as[YMap]

map.key("type", IBMMQMessageBindingModel.MessageType in binding)
map.key("headers", IBMMQMessageBindingModel.Headers in binding)
map.key("description", IBMMQMessageBindingModel.Description in binding)
map.key("expiry", IBMMQMessageBindingModel.Expiry in binding)

parseBindingVersion(binding, IBMMQMessageBindingModel.BindingVersion, map)

ctx.closedShape(binding, map, "IBMMQMessageBinding")

binding
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ object Async21Syntax extends SpecSyntax {
override val nodes: Map[String, Set[String]] =
add(
Async20Syntax.nodes,
"bindings" -> Set(Mercure),
"bindings" -> Set(Mercure, IBMMQ),
Mercure -> Set(),
IBMMQ -> Set()
IBMMQ -> Set(),
"IBMMQMessageBinding" -> Set(
"type",
"headers",
"description",
"expiry",
"bindingVersion"
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ channels:
ibmmq: {}
message:
bindings:
ibmmq: {}
ibmmq:
type: test
headers: test
description: test
expiry: 123
bindingVersion: test
payload:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
asyncapi: 2.1.0
info:
title: test mercure binding
version: 1.0.0
servers:
theName:
url: some.com
protocol: mercure
bindings:
ibmmq:
key: value
channels:
some-channel:
bindings:
ibmmq:
key: value
description: some channel
publish:
bindings:
ibmmq:
key: value
message:
bindings:
ibmmq:
type: test
headers: test
description: test
expiry: 123
bindingVersion: test
thisKeyIsNotAllowed: should throw validation error
payload:
type: string
Loading

0 comments on commit b612202

Please sign in to comment.