diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/client/platform/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/platform/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala new file mode 100644 index 0000000000..7723033976 --- /dev/null +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/platform/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala @@ -0,0 +1,132 @@ +package amf.apicontract.client.platform.model.domain.bindings.ibmmq + +import amf.apicontract.client.platform.model.domain.bindings.{BindingVersion, ChannelBinding} +import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{ + IBMMQChannelTopic => InternalIBMMQChannelTopic, + IBMMQChannelBinding => InternalIBMMQChannelBinding, + IBMMQChannelQueue => InternalIBMMQChannelQueue +} +import amf.apicontract.internal.convert.ApiClientConverters._ +import amf.core.client.platform.model +import amf.core.client.platform.model.domain.{DomainElement, NamedDomainElement} +import amf.core.client.platform.model.{BoolField, IntField, StrField} + +import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel} + +@JSExportAll +case class IBMMQChannelBinding(override private[amf] val _internal: InternalIBMMQChannelBinding) + extends ChannelBinding + with BindingVersion { + @JSExportTopLevel("IBMMQChannelBinding") + def this() = this(InternalIBMMQChannelBinding()) + + def destinationType: StrField = _internal.destinationType + def queue: IBMMQChannelQueue = _internal.queue + def topic: IBMMQChannelTopic = _internal.topic + def maxMsgLength: IntField = _internal.maxMsgLength + + def withDestinationType(destinationType: String): this.type = { + _internal.withDestinationType(destinationType) + this + } + + def withQueue(queue: IBMMQChannelQueue): this.type = { + _internal.withQueue(queue) + this + } + + def withTopic(topic: IBMMQChannelTopic): this.type = { + _internal.withTopic(topic) + this + } + + def withMaxMsgLength(maxMsgLength: Int): this.type = { + _internal.withMaxMsgLength(maxMsgLength) + this + } + + override protected def bindingVersion: model.StrField = _internal.bindingVersion + + override def withBindingVersion(bindingVersion: String): this.type = { + _internal.withBindingVersion(bindingVersion) + this + } + + override def linkCopy(): IBMMQChannelBinding = _internal.linkCopy() +} + +@JSExportAll +case class IBMMQChannelQueue(override private[amf] val _internal: InternalIBMMQChannelQueue) + extends DomainElement + with NamedDomainElement { + + @JSExportTopLevel("IBMMQChannelQueue") + def this() = this(InternalIBMMQChannelQueue()) + + def objectName: StrField = _internal.objectName + def isPartitioned: BoolField = _internal.isPartitioned + def exclusive: BoolField = _internal.exclusive + + def withObjectName(objectName: Boolean): this.type = { + _internal.withObjectName(objectName) + this + } + + def withIsPartitioned(isPartitioned: Boolean): this.type = { + _internal.withIsPartitioned(isPartitioned) + this + } + + def withExclusive(exclusive: Boolean): this.type = { + _internal.withExclusive(exclusive) + this + } + + override def name: StrField = _internal.name + + override def withName(name: String): this.type = { + _internal.withName(name) + this + } +} + +@JSExportAll +case class IBMMQChannelTopic(override private[amf] val _internal: InternalIBMMQChannelTopic) + extends DomainElement + with NamedDomainElement { + + @JSExportTopLevel("IBMMQChannelTopic") + def this() = this(InternalIBMMQChannelTopic()) + + def string: BoolField = _internal.string + def objectName: StrField = _internal.objectName + def durablePermitted: BoolField = _internal.durablePermitted + def lastMsgRetained: BoolField = _internal.lastMsgRetained + + def withString(string: Boolean): this.type = { + _internal.withString(string) + this + } + + def withObjectName(objectName: Boolean): this.type = { + _internal.withObjectName(objectName) + this + } + + def withDurablePermitted(durablePermitted: Boolean): this.type = { + _internal.withDurablePermitted(durablePermitted) + this + } + + def withLastMsgRetained(lastMsgRetained: Boolean): this.type = { + _internal.withLastMsgRetained(lastMsgRetained) + this + } + + override def name: StrField = _internal.name + + override def withName(name: String): this.type = { + _internal.withName(name) + this + } +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala new file mode 100644 index 0000000000..fd6736cd20 --- /dev/null +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/model/domain/bindings/ibmmq/IBMMQChannelBinding.scala @@ -0,0 +1,111 @@ +package amf.apicontract.client.scala.model.domain.bindings.ibmmq + +import amf.apicontract.client.scala.model.domain.bindings.{BindingVersion, ChannelBinding} +import amf.apicontract.internal.metamodel.domain.bindings.{ + IBMMQChannelBindingModel, + IBMMQChannelQueueModel, + IBMMQChannelTopicModel +} +import amf.apicontract.internal.metamodel.domain.bindings.IBMMQChannelBindingModel._ +import amf.apicontract.internal.spec.async.parser.bindings.Bindings.IBMMQ +import amf.core.client.scala.model.domain.{DomainElement, Linkable, NamedDomainElement} +import amf.core.client.scala.model.{BoolField, IntField, StrField} +import amf.core.internal.metamodel.Field +import amf.core.internal.parser.domain.{Annotations, Fields} +import amf.shapes.client.scala.model.domain.Key + +class IBMMQChannelBinding(override val fields: Fields, override val annotations: Annotations) + extends ChannelBinding + with BindingVersion + with Key { + + override protected def bindingVersionField: Field = BindingVersion + override def meta: IBMMQChannelBindingModel.type = IBMMQChannelBindingModel + + def destinationType: StrField = fields.field(DestinationType) + def queue: IBMMQChannelQueue = fields.field(Queue) + def topic: IBMMQChannelTopic = fields.field(Topic) + def maxMsgLength: IntField = fields.field(MaxMsgLength) + + def withDestinationType(destinationType: String): this.type = set(DestinationType, destinationType) + def withQueue(queue: IBMMQChannelQueue): this.type = set(Queue, queue) + def withTopic(topic: IBMMQChannelTopic): this.type = set(Topic, topic) + def withMaxMsgLength(maxMsgLength: Int): this.type = set(MaxMsgLength, maxMsgLength) + + override def key: StrField = fields.field(IBMMQChannelBindingModel.key) + + override def componentId: String = s"/$IBMMQ-channel" + + override def linkCopy(): IBMMQChannelBinding = IBMMQChannelBinding() + + override protected def classConstructor: (Fields, Annotations) => Linkable with DomainElement = + IBMMQChannelBinding.apply +} + +object IBMMQChannelBinding { + + def apply(): IBMMQChannelBinding = apply(Annotations()) + + def apply(annotations: Annotations): IBMMQChannelBinding = apply(Fields(), annotations) + + def apply(fields: Fields, annotations: Annotations): IBMMQChannelBinding = + new IBMMQChannelBinding(fields, annotations) +} + +class IBMMQChannelQueue(override val fields: Fields, override val annotations: Annotations) + extends DomainElement + with NamedDomainElement { + override def meta: IBMMQChannelQueueModel.type = IBMMQChannelQueueModel + + override def nameField: Field = IBMMQChannelQueueModel.Name + + def objectName: StrField = fields.field(IBMMQChannelQueueModel.ObjectName) + def isPartitioned: BoolField = fields.field(IBMMQChannelQueueModel.IsPartitioned) + def exclusive: BoolField = fields.field(IBMMQChannelQueueModel.Exclusive) + + def withObjectName(objectName: Boolean): this.type = set(IBMMQChannelQueueModel.ObjectName, objectName) + def withIsPartitioned(isPartitioned: Boolean): this.type = set(IBMMQChannelQueueModel.IsPartitioned, isPartitioned) + def withExclusive(exclusive: Boolean): this.type = set(IBMMQChannelQueueModel.Exclusive, exclusive) + + override def componentId: String = s"/$IBMMQ-queue" +} + +object IBMMQChannelQueue { + + def apply(): IBMMQChannelQueue = apply(Annotations()) + + def apply(annotations: Annotations): IBMMQChannelQueue = apply(Fields(), annotations) + + def apply(fields: Fields, annotations: Annotations): IBMMQChannelQueue = new IBMMQChannelQueue(fields, annotations) +} + +class IBMMQChannelTopic(override val fields: Fields, override val annotations: Annotations) + extends DomainElement + with NamedDomainElement { + override def meta: IBMMQChannelTopicModel.type = IBMMQChannelTopicModel + + override def nameField: Field = IBMMQChannelTopicModel.Name + + def string: BoolField = fields.field(IBMMQChannelTopicModel.String) + def objectName: StrField = fields.field(IBMMQChannelTopicModel.ObjectName) + def durablePermitted: BoolField = fields.field(IBMMQChannelTopicModel.DurablePermitted) + def lastMsgRetained: BoolField = fields.field(IBMMQChannelTopicModel.LastMsgRetained) + + def withString(string: Boolean): this.type = set(IBMMQChannelTopicModel.String, string) + def withObjectName(objectName: Boolean): this.type = set(IBMMQChannelTopicModel.ObjectName, objectName) + def withDurablePermitted(durablePermitted: Boolean): this.type = + set(IBMMQChannelTopicModel.DurablePermitted, durablePermitted) + def withLastMsgRetained(lastMsgRetained: Boolean): this.type = + set(IBMMQChannelTopicModel.LastMsgRetained, lastMsgRetained) + + override def componentId: String = s"/$IBMMQ-topic" +} + +object IBMMQChannelTopic { + + def apply(): IBMMQChannelTopic = apply(Annotations()) + + def apply(annotations: Annotations): IBMMQChannelTopic = apply(Fields(), annotations) + + def apply(fields: Fields, annotations: Annotations): IBMMQChannelTopic = new IBMMQChannelTopic(fields, annotations) +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiBaseConverter.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiBaseConverter.scala index fdf434315d..d4029e386d 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiBaseConverter.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiBaseConverter.scala @@ -30,7 +30,13 @@ 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, IBMMQServerBinding} +import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{ + IBMMQChannelBinding, + IBMMQChannelQueue, + IBMMQChannelTopic, + IBMMQMessageBinding, + IBMMQServerBinding +} import amf.apicontract.client.scala.model.domain.bindings.kafka.{KafkaMessageBinding, KafkaOperationBinding} import amf.apicontract.client.scala.model.domain.bindings.mqtt.{ MqttMessageBinding, @@ -115,6 +121,9 @@ trait ApiBaseConverter with Amqp091QueueConverter with IBBMQMessageBindingConverter with IBBMQServerBindingConverter + with IBBMQChannelBindingConverter + with IBBMQChannelQueueConverter + with IBBMQChannelTopicConverter with ChannelBindingConverter with OperationBindingConverter with MessageBindingConverter @@ -332,6 +341,33 @@ trait IBBMQServerBindingConverter extends PlatformSecrets { } } +trait IBBMQChannelBindingConverter extends PlatformSecrets { + implicit object IBBMQChannelBindingMatcher + extends BidirectionalMatcher[IBMMQChannelBinding, domain.bindings.ibmmq.IBMMQChannelBinding] { + override def asClient(from: IBMMQChannelBinding): domain.bindings.ibmmq.IBMMQChannelBinding = + platform.wrap[domain.bindings.ibmmq.IBMMQChannelBinding](from) + override def asInternal(from: domain.bindings.ibmmq.IBMMQChannelBinding): IBMMQChannelBinding = from._internal + } +} + +trait IBBMQChannelQueueConverter extends PlatformSecrets { + implicit object IBBMQChannelQueueMatcher + extends BidirectionalMatcher[IBMMQChannelQueue, domain.bindings.ibmmq.IBMMQChannelQueue] { + override def asClient(from: IBMMQChannelQueue): domain.bindings.ibmmq.IBMMQChannelQueue = + platform.wrap[domain.bindings.ibmmq.IBMMQChannelQueue](from) + override def asInternal(from: domain.bindings.ibmmq.IBMMQChannelQueue): IBMMQChannelQueue = from._internal + } +} + +trait IBBMQChannelTopicConverter extends PlatformSecrets { + implicit object IBBMQChannelTopicMatcher + extends BidirectionalMatcher[IBMMQChannelTopic, domain.bindings.ibmmq.IBMMQChannelTopic] { + override def asClient(from: IBMMQChannelTopic): domain.bindings.ibmmq.IBMMQChannelTopic = + platform.wrap[domain.bindings.ibmmq.IBMMQChannelTopic](from) + override def asInternal(from: domain.bindings.ibmmq.IBMMQChannelTopic): IBMMQChannelTopic = from._internal + } +} + trait EndPointConverter extends PlatformSecrets { implicit object EndPointMatcher extends BidirectionalMatcher[EndPoint, domain.EndPoint] { diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiRegister.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiRegister.scala index 39b2fadabc..48c55cd80a 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiRegister.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/convert/ApiRegister.scala @@ -6,7 +6,13 @@ 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, IBMMQServerBinding} +import amf.apicontract.client.platform.model.domain.bindings.ibmmq.{ + IBMMQChannelBinding, + IBMMQChannelQueue, + IBMMQChannelTopic, + IBMMQMessageBinding, + IBMMQServerBinding +} import amf.apicontract.client.platform.model.domain.bindings.kafka.{KafkaMessageBinding, KafkaOperationBinding} import amf.apicontract.client.platform.model.domain.bindings.mqtt.{ MqttMessageBinding, @@ -281,6 +287,15 @@ private[amf] object ApiRegister extends UniqueInitializer with PlatformSecrets { platform.registerWrapper(IBMMQServerBindingModel) { case s: amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQServerBinding => IBMMQServerBinding(s) } + platform.registerWrapper(IBMMQChannelBindingModel) { + case s: amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQChannelBinding => IBMMQChannelBinding(s) + } + platform.registerWrapper(IBMMQChannelQueueModel) { + case s: amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQChannelQueue => IBMMQChannelQueue(s) + } + platform.registerWrapper(IBMMQChannelTopicModel) { + case s: amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQChannelTopic => IBMMQChannelTopic(s) + } platform.registerWrapper(APIContractProcessingDataModel) { case s: amf.apicontract.client.scala.model.document.APIContractProcessingData => APIContractProcessingData(s) } diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/entities/APIEntities.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/entities/APIEntities.scala index adb230fac2..20f3f9edfe 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/entities/APIEntities.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/entities/APIEntities.scala @@ -96,6 +96,9 @@ private[amf] object APIEntities extends Entities { ParameterFederationMetadataModel, EndpointFederationMetadataModel, IBMMQMessageBindingModel, - IBMMQServerBindingModel + IBMMQServerBindingModel, + IBMMQChannelBindingModel, + IBMMQChannelQueueModel, + IBMMQChannelTopicModel ) } diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/metamodel/domain/bindings/IBMMQBindingModel.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/metamodel/domain/bindings/IBMMQBindingModel.scala index 98b7ee11d6..f1735f331f 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/metamodel/domain/bindings/IBMMQBindingModel.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/metamodel/domain/bindings/IBMMQBindingModel.scala @@ -1,12 +1,19 @@ package amf.apicontract.internal.metamodel.domain.bindings -import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{IBMMQMessageBinding, IBMMQServerBinding} +import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{ + IBMMQChannelBinding, + IBMMQChannelQueue, + IBMMQChannelTopic, + IBMMQMessageBinding, + IBMMQServerBinding +} 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.{Bool, Int, Str} -import amf.core.internal.metamodel.domain.{ModelDoc, ModelVocabularies} +import amf.core.internal.metamodel.domain.common.NameFieldSchema +import amf.core.internal.metamodel.domain.{DomainElementModel, ModelDoc, ModelVocabularies} object IBMMQMessageBindingModel extends MessageBindingModel with BindingVersion { val MessageType: Field = @@ -135,3 +142,147 @@ object IBMMQServerBindingModel extends ServerBindingModel with BindingVersion { override val doc: ModelDoc = ModelDoc(ModelVocabularies.ApiBinding, "IBMMQServerBinding") } + +object IBMMQChannelBindingModel extends ChannelBindingModel with BindingVersion { + val DestinationType: Field = + Field( + Str, + ApiBinding + "destinationType", + ModelDoc( + ModelVocabularies.ApiBinding, + "destinationType", + "Defines the type of AsyncAPI channel." + ) + ) + + val Queue: Field = + Field( + IBMMQChannelQueueModel, + ApiBinding + "queue", + ModelDoc( + ModelVocabularies.ApiBinding, + "queue", + "Defines the properties of a queue." + ) + ) + + val Topic: Field = + Field( + IBMMQChannelTopicModel, + ApiBinding + "topic", + ModelDoc( + ModelVocabularies.ApiBinding, + "topic", + "Defines the properties of a topic." + ) + ) + + val MaxMsgLength: Field = + Field( + Int, + ApiBinding + "maxMsgLength", + ModelDoc( + ModelVocabularies.ApiBinding, + "maxMsgLength", + "The maximum length of the physical message (in bytes) accepted by the Topic or Queue. Messages produced that are greater in size than this value may fail to be delivered." + ) + ) + + override def modelInstance: AmfObject = IBMMQChannelBinding() + + override def fields: List[Field] = + List( + BindingVersion + ) ++ ChannelBindingModel.fields + + override val `type`: List[ValueType] = ApiBinding + "IBMMQChannelBinding" :: ChannelBindingModel.`type` + + override val key: Field = Type + + override val doc: ModelDoc = ModelDoc(ModelVocabularies.ApiBinding, "IBMMQChannelBinding") +} + +object IBMMQChannelQueueModel extends DomainElementModel with NameFieldSchema { + + val ObjectName: Field = Field( + Str, + ApiBinding + "objectName", + ModelDoc( + ModelVocabularies.ApiBinding, + "objectName", + "Defines the name of the IBM MQ queue associated with the channel." + ) + ) + + val IsPartitioned: Field = Field( + Bool, + ApiBinding + "isPartitioned", + ModelDoc( + ModelVocabularies.ApiBinding, + "isPartitioned", + "Defines if the queue is a cluster queue and therefore partitioned. If true, a binding option MAY be specified when accessing the queue." + ) + ) + + val Exclusive: Field = Field( + Bool, + ApiBinding + "exclusive", + ModelDoc(ModelVocabularies.ApiBinding, "exclusive", "Specifies if it is recommended to open the queue exclusively.") + ) + + override def fields: List[Field] = List(ObjectName, IsPartitioned, Exclusive) ++ DomainElementModel.fields + + override val `type`: List[ValueType] = ApiBinding + "IBMMQChannelQueue" :: DomainElementModel.`type` + + override def modelInstance: AmfObject = IBMMQChannelQueue() + + override val doc: ModelDoc = ModelDoc(ModelVocabularies.ApiBinding, "IBMMQChannelQueue") +} + +object IBMMQChannelTopicModel extends DomainElementModel with NameFieldSchema { + + val String: Field = Field( + Str, + ApiBinding + "string", + ModelDoc( + ModelVocabularies.ApiBinding, + "string", + "The value of the IBM MQ topic string to be used." + ) + ) + + val ObjectName: Field = Field( + Str, + ApiBinding + "objectName", + ModelDoc( + ModelVocabularies.ApiBinding, + "objectName", + "The name of the IBM MQ topic object." + ) + ) + + val DurablePermitted: Field = Field( + Bool, + ApiBinding + "durablePermitted", + ModelDoc(ModelVocabularies.ApiBinding, "durablePermitted", "Defines if the subscription may be durable.") + ) + + val LastMsgRetained: Field = Field( + Bool, + ApiBinding + "lastMsgRetained", + ModelDoc( + ModelVocabularies.ApiBinding, + "lastMsgRetained", + "Defines if the last message published will be made available to new subscriptions." + ) + ) + + override def fields: List[Field] = + List(String, ObjectName, DurablePermitted, LastMsgRetained) ++ DomainElementModel.fields + + override val `type`: List[ValueType] = ApiBinding + "IBMMQChannelTopic" :: DomainElementModel.`type` + + override def modelInstance: AmfObject = IBMMQChannelTopic() + + override val doc: ModelDoc = ModelDoc(ModelVocabularies.ApiBinding, "IBMMQChannelTopic") +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/emitters/bindings/AsyncApiChannelBindingsEmitter.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/emitters/bindings/AsyncApiChannelBindingsEmitter.scala index 634cbcf2c9..4225ae3a8f 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/emitters/bindings/AsyncApiChannelBindingsEmitter.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/emitters/bindings/AsyncApiChannelBindingsEmitter.scala @@ -6,14 +6,23 @@ import amf.apicontract.client.scala.model.domain.bindings.amqp.{ Amqp091ChannelExchange, Amqp091Queue } +import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{ + IBMMQChannelBinding, + IBMMQChannelQueue, + IBMMQChannelTopic +} import amf.apicontract.client.scala.model.domain.bindings.websockets.WebSocketsChannelBinding import amf.apicontract.internal.metamodel.domain.bindings.{ Amqp091ChannelBindingModel, Amqp091ChannelExchangeModel, Amqp091QueueModel, + IBMMQChannelBindingModel, + IBMMQChannelQueueModel, + IBMMQChannelTopicModel, WebSocketsChannelBindingModel } import amf.apicontract.internal.spec.async.emitters.domain +import amf.apicontract.internal.spec.async.parser.bindings.Bindings.IBMMQ import amf.apicontract.internal.spec.oas.emitter.context.OasLikeSpecEmitterContext import org.mulesoft.common.client.lexical.Position import amf.core.client.scala.model.domain.Shape @@ -38,6 +47,7 @@ class AsyncApiChannelBindingsEmitter(binding: ChannelBinding, ordering: SpecOrde private def emitterFor(binding: ChannelBinding): Option[EntryEmitter] = binding match { case binding: Amqp091ChannelBinding => Some(new Amqp091ChannelBindingEmitter(binding, ordering)) case binding: WebSocketsChannelBinding => Some(new WebSocketChannelBindingEmitter(binding, ordering)) + case binding: IBMMQChannelBinding => Some(new IBMMQChannelBindingEmitter(binding, ordering)) case _ => None } @@ -144,3 +154,79 @@ class Amqp091ChannelQueueEmitter(binding: Amqp091Queue, ordering: SpecOrdering) override def position(): Position = pos(binding.annotations) } + +class IBMMQChannelBindingEmitter(binding: IBMMQChannelBinding, ordering: SpecOrdering) + extends AsyncApiCommonBindingEmitter { + + override def emit(b: YDocument.EntryBuilder): Unit = { + b.entry( + YNode(IBMMQ), + _.obj { emitter => + val result = ListBuffer[EntryEmitter]() + val fs = binding.fields + + fs.entry(IBMMQChannelBindingModel.DestinationType).foreach(f => result += ValueEmitter("destinationType", f)) + fs.entry(IBMMQChannelBindingModel.MaxMsgLength) + .foreach(f => result += ValueEmitter("maxMsgLength", f)) + + result ++= emitQueueAndTopicProperties + + emitBindingVersion(fs, result) + + traverse(ordering.sorted(result), emitter) + } + ) + } + + private def emitQueueAndTopicProperties: Seq[EntryEmitter] = { + val result = ListBuffer[EntryEmitter]() + Option(binding.queue).foreach(queue => result += new IBMMQChannelQueueEmitter(queue, ordering)) + Option(binding.topic).foreach(topic => result += new IBMMQChannelTopicEmitter(topic, ordering)) + result.toList + } + + override def position(): Position = pos(binding.annotations) +} + +class IBMMQChannelQueueEmitter(binding: IBMMQChannelQueue, ordering: SpecOrdering) extends EntryEmitter { + + override def emit(b: EntryBuilder): Unit = { + b.entry( + YNode("queue"), + _.obj { emitter => + val result = ListBuffer[EntryEmitter]() + val fs = binding.fields + + fs.entry(IBMMQChannelQueueModel.ObjectName).foreach(f => result += ValueEmitter("objectName", f)) + fs.entry(IBMMQChannelQueueModel.IsPartitioned).foreach(f => result += ValueEmitter("isPartitioned", f)) + fs.entry(IBMMQChannelQueueModel.Exclusive).foreach(f => result += ValueEmitter("exclusive", f)) + + traverse(ordering.sorted(result), emitter) + } + ) + } + + override def position(): Position = pos(binding.annotations) +} + +class IBMMQChannelTopicEmitter(binding: IBMMQChannelTopic, ordering: SpecOrdering) extends EntryEmitter { + + override def emit(b: EntryBuilder): Unit = { + b.entry( + YNode("topic"), + _.obj { emitter => + val result = ListBuffer[EntryEmitter]() + val fs = binding.fields + + fs.entry(IBMMQChannelTopicModel.String).foreach(f => result += ValueEmitter("string", f)) + fs.entry(IBMMQChannelTopicModel.ObjectName).foreach(f => result += ValueEmitter("objectName", f)) + fs.entry(IBMMQChannelTopicModel.DurablePermitted).foreach(f => result += ValueEmitter("durablePermitted", f)) + fs.entry(IBMMQChannelTopicModel.LastMsgRetained).foreach(f => result += ValueEmitter("lastMsgRetained", f)) + + traverse(ordering.sorted(result), emitter) + } + ) + } + + override def position(): Position = pos(binding.annotations) +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/AsyncChannelBindingsParser.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/AsyncChannelBindingsParser.scala index 22eaaeedcd..1ee50e03ea 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/AsyncChannelBindingsParser.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/AsyncChannelBindingsParser.scala @@ -2,9 +2,10 @@ package amf.apicontract.internal.spec.async.parser.bindings import amf.apicontract.client.scala.model.domain.bindings.{ChannelBinding, ChannelBindings} import amf.apicontract.internal.metamodel.domain.bindings._ -import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{Amqp, Http, Kafka, Mqtt, WebSockets} +import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{Amqp, IBMMQ, WebSockets} import amf.apicontract.internal.spec.async.parser.bindings.channel.{ Amqp091ChannelBindingParser, + IBMMQChannelBindingParser, WebSocketsChannelBindingParser } import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext @@ -14,12 +15,12 @@ import amf.core.client.scala.model.domain.AmfScalar import amf.core.internal.metamodel.Field import amf.core.internal.parser.domain.{Annotations, SearchScope} import amf.shapes.internal.spec.common.parser.YMapEntryLike -import org.yaml.model.YMapEntry object AsyncChannelBindingsParser { private val parserMap: Map[String, BindingParser[ChannelBinding]] = Map( Amqp -> Amqp091ChannelBindingParser, - WebSockets -> WebSocketsChannelBindingParser + WebSockets -> WebSocketsChannelBindingParser, + IBMMQ -> IBMMQChannelBindingParser ) } diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/channel/IBMMQChannelBindingParser.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/channel/IBMMQChannelBindingParser.scala new file mode 100644 index 0000000000..9811c5f5db --- /dev/null +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/bindings/channel/IBMMQChannelBindingParser.scala @@ -0,0 +1,74 @@ +package amf.apicontract.internal.spec.async.parser.bindings.channel + +import amf.apicontract.client.scala.model.domain.bindings.ibmmq.{ + IBMMQChannelBinding, + IBMMQChannelQueue, + IBMMQChannelTopic +} +import amf.apicontract.internal.metamodel.domain.bindings.{ + IBMMQChannelBindingModel, + IBMMQChannelQueueModel, + IBMMQChannelTopicModel, + WebSocketsChannelBindingModel +} +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 IBMMQChannelBindingParser extends BindingParser[IBMMQChannelBinding] { + override def parse(entry: YMapEntry, parent: String)(implicit ctx: AsyncWebApiContext): IBMMQChannelBinding = { + val binding = IBMMQChannelBinding(Annotations(entry)) + val map = entry.value.as[YMap] + + map.key("destinationType", IBMMQChannelBindingModel.DestinationType in binding) + map.key("maxMsgLength", IBMMQChannelBindingModel.MaxMsgLength in binding) + + parseQueue(binding, map) + parseTopic(binding, map) + + parseBindingVersion(binding, WebSocketsChannelBindingModel.BindingVersion, map) + + ctx.closedShape(binding, map, "IBMMQChannelBinding") + + binding + } + + private def parseQueue(binding: IBMMQChannelBinding, map: YMap)(implicit ctx: AsyncWebApiContext): Unit = { + map.key( + "queue", + { entry => + val queue = IBMMQChannelQueue(Annotations(entry.value)) + val queueMap = entry.value.as[YMap] + + queueMap.key("objectName", IBMMQChannelQueueModel.ObjectName in queue) + queueMap.key("isPartitioned", IBMMQChannelQueueModel.IsPartitioned in queue) + queueMap.key("exclusive", IBMMQChannelQueueModel.Exclusive in queue) + + ctx.closedShape(queue, queueMap, "IBMMQChannelQueue") + + binding.setWithoutId(IBMMQChannelBindingModel.Queue, queue, Annotations(entry)) + } + ) + } + + private def parseTopic(binding: IBMMQChannelBinding, map: YMap)(implicit ctx: AsyncWebApiContext): Unit = { + map.key( + "topic", + { entry => + val topic = IBMMQChannelTopic(Annotations(entry.value)) + val topicMap = entry.value.as[YMap] + + topicMap.key("string", IBMMQChannelTopicModel.String in topic) + topicMap.key("objectName", IBMMQChannelTopicModel.ObjectName in topic) + topicMap.key("durablePermitted", IBMMQChannelTopicModel.DurablePermitted in topic) + topicMap.key("lastMsgRetained", IBMMQChannelTopicModel.LastMsgRetained in topic) + + ctx.closedShape(topic, topicMap, "IBMMQChannelTopic") + + binding.setWithoutId(IBMMQChannelBindingModel.Topic, topic, Annotations(entry)) + } + ) + } +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/AsyncValidBindingSet.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/AsyncValidBindingSet.scala index c5e1623083..44e1657ffe 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/AsyncValidBindingSet.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/AsyncValidBindingSet.scala @@ -3,8 +3,8 @@ package amf.apicontract.internal.spec.async.parser.context import amf.apicontract.internal.spec.async.parser.bindings.Bindings._ case class AsyncValidBindingSet(bindings: Set[String]) { - def add(bindings: String*) = copy(this.bindings ++ bindings) - def canParse(binding: String): Boolean = bindings.contains(binding) + def add(bindings: String*): AsyncValidBindingSet = copy(this.bindings ++ bindings) + def canParse(binding: String): Boolean = bindings.contains(binding) } object AsyncValidBindingSet { diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/syntax/Async21Syntax.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/syntax/Async21Syntax.scala index b8da65d4fe..f698d94c98 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/syntax/Async21Syntax.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/async/parser/context/syntax/Async21Syntax.scala @@ -22,6 +22,24 @@ object Async21Syntax extends SpecSyntax { "multiEndpointServer", "heartBeatInterval", "bindingVersion" + ), + "IBMMQChannelBinding" -> Set( + "destinationType", + "queue", + "topic", + "maxMsgLength", + "bindingVersion" + ), + "IBMMQChannelQueue" -> Set( + "objectName", + "isPartitioned", + "exclusive" + ), + "IBMMQChannelTopic" -> Set( + "string", + "objectName", + "durablePermitted", + "lastMsgRetained" ) ) } diff --git a/amf-cli/shared/src/test/resources/upanddown/cycle/async20/bindings/ibmmq-binding.yaml b/amf-cli/shared/src/test/resources/upanddown/cycle/async20/bindings/ibmmq-binding.yaml index fd3d493435..6f0fcf2b50 100644 --- a/amf-cli/shared/src/test/resources/upanddown/cycle/async20/bindings/ibmmq-binding.yaml +++ b/amf-cli/shared/src/test/resources/upanddown/cycle/async20/bindings/ibmmq-binding.yaml @@ -16,7 +16,19 @@ servers: channels: some-channel: bindings: - ibmmq: {} + ibmmq: + destinationType: test + queue: + objectName: test + isPartitioned: true + exclusive: false + topic: + string: test + objectName: test + durablePermitted: true + lastMsgRetained: false + maxMsgLength: 123 + bindingVersion: test description: some channel publish: bindings: diff --git a/amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml b/amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml index f2d619bb2c..292c9a9b9a 100644 --- a/amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml +++ b/amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml @@ -18,7 +18,21 @@ channels: some-channel: bindings: ibmmq: - key: value + destinationType: test + queue: + objectName: test + isPartitioned: true + exclusive: false + thisKeyIsNotAllowed: should throw validation error + topic: + string: test + objectName: test + durablePermitted: true + lastMsgRetained: false + thisKeyIsNotAllowed: should throw validation error + maxMsgLength: 123 + bindingVersion: test + thisKeyIsNotAllowed: should throw validation error description: some channel publish: bindings: diff --git a/amf-cli/shared/src/test/resources/validations/reports/async20/ibmmq-binding-extra-key.report b/amf-cli/shared/src/test/resources/validations/reports/async20/ibmmq-binding-extra-key.report index b35f999988..80397d0874 100644 --- a/amf-cli/shared/src/test/resources/validations/reports/async20/ibmmq-binding-extra-key.report +++ b/amf-cli/shared/src/test/resources/validations/reports/async20/ibmmq-binding-extra-key.report @@ -1,7 +1,7 @@ ModelId: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml Profile: Conforms: false -Number of results: 4 +Number of results: 6 Level: Violation @@ -13,12 +13,28 @@ Level: Violation Range: [(16,8)-(17,0)] Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml -- Constraint: http://a.ml/vocabularies/amf/parser#non-empty-binding-map - Message: Reserved name binding 'ibmmq' must have an empty map +- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape + Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.1 IBMMQChannelQueue node + Severity: Violation + Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/channel-bindings/bindings/ibmmq-channel/ibmmq-queue + Property: + Range: [(26,10)-(27,0)] + Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml + +- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape + Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.1 IBMMQChannelTopic node + Severity: Violation + Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/channel-bindings/bindings/ibmmq-channel/ibmmq-topic + Property: + Range: [(32,10)-(33,0)] + Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml + +- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape + Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.1 IBMMQChannelBinding node Severity: Violation - Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/channel-bindings/bindings/ibmmq + Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/channel-bindings/bindings/ibmmq-channel Property: - Range: [(20,12)-(22,0)] + Range: [(35,8)-(36,0)] Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml - Constraint: http://a.ml/vocabularies/amf/parser#non-empty-binding-map @@ -26,7 +42,7 @@ Level: Violation Severity: Violation Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/supportedOperation/publish/operation-bindings/bindings/ibmmq Property: - Range: [(25,14)-(27,0)] + Range: [(39,14)-(41,0)] Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml - Constraint: http://a.ml/vocabularies/amf/parser#closed-shape @@ -34,5 +50,5 @@ Level: Violation Severity: Violation Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml#/async-api/endpoint/some-channel/supportedOperation/publish/expects/request/message-bindings/bindings/ibmmq-message Property: - Range: [(35,12)-(36,0)] + Range: [(49,12)-(50,0)] Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/ibmmq-binding-extra-key.yaml diff --git a/documentation/model.md b/documentation/model.md index 8045206101..19374ffd42 100644 --- a/documentation/model.md +++ b/documentation/model.md @@ -76,6 +76,9 @@ AMF Model Documentation * [HttpMessageBinding](#httpmessagebinding) * [HttpOperationBinding](#httpoperationbinding) * [HttpSettings](#httpsettings) +* [IBMMQChannelBinding](#ibmmqchannelbinding) +* [IBMMQChannelQueue](#ibmmqchannelqueue) +* [IBMMQChannelTopic](#ibmmqchanneltopic) * [IBMMQMessageBinding](#ibmmqmessagebinding) * [IBMMQServerBinding](#ibmmqserverbinding) * [IriTemplateMapping](#iritemplatemapping) @@ -1502,6 +1505,46 @@ Types: | additionalProperties | [DataNode](#datanode) | - | | `http://a.ml/vocabularies/security#additionalProperties` | | extends | [[DomainElement](#domainelement)] | false | Entity that is going to be extended overlaying or adding additional information The type of the relationship provide the semantics about thow the referenced and referencer elements must be combined when generating the domain model from the document model. | `http://a.ml/vocabularies/document#extends` | +## IBMMQChannelBinding + +Types: +* `http://a.ml/vocabularies/apiBinding#IBMMQChannelBinding` +* `http://a.ml/vocabularies/apiBinding#ChannelBinding` +* `http://a.ml/vocabularies/document#DomainElement` + + | Name | Value | Sorted | Documentation | Namespace | + | ------ | ------ | ------ | ------ | ------ | + | bindingVersion | string | - | The version of this binding | `http://a.ml/vocabularies/apiBinding#bindingVersion` | + | type | string | - | Binding for a corresponding known type | `http://a.ml/vocabularies/apiBinding#type` | + | extends | [[DomainElement](#domainelement)] | false | Entity that is going to be extended overlaying or adding additional information The type of the relationship provide the semantics about thow the referenced and referencer elements must be combined when generating the domain model from the document model. | `http://a.ml/vocabularies/document#extends` | + +## IBMMQChannelQueue + +Types: +* `http://a.ml/vocabularies/apiBinding#IBMMQChannelQueue` +* `http://a.ml/vocabularies/document#DomainElement` + + | Name | Value | Sorted | Documentation | Namespace | + | ------ | ------ | ------ | ------ | ------ | + | objectName | string | - | Defines the name of the IBM MQ queue associated with the channel. | `http://a.ml/vocabularies/apiBinding#objectName` | + | isPartitioned | boolean | - | Defines if the queue is a cluster queue and therefore partitioned. If true, a binding option MAY be specified when accessing the queue. | `http://a.ml/vocabularies/apiBinding#isPartitioned` | + | exclusive | boolean | - | Specifies if it is recommended to open the queue exclusively. | `http://a.ml/vocabularies/apiBinding#exclusive` | + | extends | [[DomainElement](#domainelement)] | false | Entity that is going to be extended overlaying or adding additional information The type of the relationship provide the semantics about thow the referenced and referencer elements must be combined when generating the domain model from the document model. | `http://a.ml/vocabularies/document#extends` | + +## IBMMQChannelTopic + +Types: +* `http://a.ml/vocabularies/apiBinding#IBMMQChannelTopic` +* `http://a.ml/vocabularies/document#DomainElement` + + | Name | Value | Sorted | Documentation | Namespace | + | ------ | ------ | ------ | ------ | ------ | + | string | string | - | The value of the IBM MQ topic string to be used. | `http://a.ml/vocabularies/apiBinding#string` | + | objectName | string | - | The name of the IBM MQ topic object. | `http://a.ml/vocabularies/apiBinding#objectName` | + | durablePermitted | boolean | - | Defines if the subscription may be durable. | `http://a.ml/vocabularies/apiBinding#durablePermitted` | + | lastMsgRetained | boolean | - | Defines if the last message published will be made available to new subscriptions. | `http://a.ml/vocabularies/apiBinding#lastMsgRetained` | + | extends | [[DomainElement](#domainelement)] | false | Entity that is going to be extended overlaying or adding additional information The type of the relationship provide the semantics about thow the referenced and referencer elements must be combined when generating the domain model from the document model. | `http://a.ml/vocabularies/document#extends` | + ## IBMMQMessageBinding Types: