Skip to content

Commit

Permalink
W-12689958: add Solace binding parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
arielmirra committed Mar 14, 2024
1 parent 6e82511 commit 82eb262
Show file tree
Hide file tree
Showing 10 changed files with 592 additions and 371 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package amf.apicontract.internal.spec.async.parser.bindings
import amf.apicontract.client.scala.model.domain.bindings.{OperationBinding, OperationBindings}
import amf.apicontract.internal.metamodel.domain.bindings._
import amf.apicontract.internal.spec.async.parser.bindings.AsyncOperationBindingsParser.parserMap
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{Amqp, Http, Kafka, Mqtt}
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{Amqp, Http, Kafka, Mqtt, Solace}
import amf.apicontract.internal.spec.async.parser.bindings.operation.{
Amqp091OperationBindingParser,
HttpOperationBindingParser,
KafkaOperationBindingParser,
MqttOperationBindingParser
MqttOperationBindingParser,
SolaceOperationBindingParser
}
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.apicontract.internal.spec.common.WebApiDeclarations.ErrorOperationBindings
Expand All @@ -20,10 +21,11 @@ import amf.shapes.internal.spec.common.parser.YMapEntryLike

object AsyncOperationBindingsParser {
private val parserMap: Map[String, BindingParser[OperationBinding]] = Map(
Amqp -> Amqp091OperationBindingParser,
Http -> HttpOperationBindingParser,
Kafka -> KafkaOperationBindingParser,
Mqtt -> MqttOperationBindingParser
Amqp -> Amqp091OperationBindingParser,
Http -> HttpOperationBindingParser,
Kafka -> KafkaOperationBindingParser,
Mqtt -> MqttOperationBindingParser,
Solace -> SolaceOperationBindingParser
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package amf.apicontract.internal.spec.async.parser.bindings

import amf.apicontract.client.scala.model.domain.bindings.{ServerBinding, ServerBindings}
import amf.apicontract.internal.metamodel.domain.bindings.ServerBindingsModel
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{IBMMQ, Mqtt}
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.{IBMMQ, Mqtt, Solace}
import amf.apicontract.internal.spec.async.parser.bindings.server._
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.apicontract.internal.spec.common.WebApiDeclarations.ErrorServerBindings
Expand All @@ -14,8 +14,9 @@ import amf.shapes.internal.spec.common.parser.YMapEntryLike

object AsyncServerBindingsParser {
private val parserMap: Map[String, BindingParser[ServerBinding]] = Map(
Mqtt -> MqttServerBindingParser,
IBMMQ -> IBMMQServerBindingParser
Mqtt -> MqttServerBindingParser,
IBMMQ -> IBMMQServerBindingParser,
Solace -> SolaceServerBindingParser
)
}
case class AsyncServerBindingsParser(entryLike: YMapEntryLike)(implicit ctx: AsyncWebApiContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package amf.apicontract.internal.spec.async.parser.bindings
import amf.apicontract.client.scala.model.domain.bindings.BindingVersion
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.apicontract.internal.spec.common.parser.SpecParserOps
import amf.core.client.scala.model.domain.{AmfElement, AmfScalar, DomainElement, Linkable}
import amf.core.client.scala.model.domain.{AmfElement, AmfObject, AmfScalar, DomainElement, Linkable}
import amf.core.internal.metamodel.Field
import amf.core.internal.parser.YMapOps
import amf.core.internal.parser.domain.Annotations
Expand All @@ -24,8 +24,8 @@ trait BindingParser[+Binding <: DomainElement] extends SpecParserOps {
if (bindingVersionIsEmpty(binding)) setDefaultBindingVersionValue(binding, field)
}

protected def setDefaultValue(binding: BindingVersion, field: Field, element: AmfElement): binding.type = {
binding.setWithoutId(field, element, Annotations.synthesized())
protected def setDefaultValue(obj: AmfObject, field: Field, element: AmfElement): obj.type = {
obj.setWithoutId(field, element, Annotations.synthesized())
}

private def setDefaultBindingVersionValue(binding: BindingVersion, field: Field) = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package amf.apicontract.internal.spec.async.parser.bindings.operation

import amf.apicontract.client.scala.model.domain.bindings.solace.{
SolaceOperationBinding,
SolaceOperationDestination,
SolaceOperationQueue,
SolaceOperationTopic
}
import amf.apicontract.internal.metamodel.domain.bindings.{
SolaceOperationBindingModel,
SolaceOperationDestinationModel,
SolaceOperationQueueModel,
SolaceOperationTopicModel
}
import amf.apicontract.internal.spec.async.parser.bindings.BindingParser
import amf.apicontract.internal.spec.async.parser.context.AsyncWebApiContext
import amf.core.client.scala.model.domain.AmfScalar
import amf.core.internal.parser.domain.Annotations
import org.yaml.model.{YMap, YMapEntry}
import amf.core.internal.parser.YMapOps

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

map.key("destinations").foreach { entry =>
val destinations = entry.value.as[Seq[YMap]].map(destinationMap => parseDestination(binding, destinationMap))
binding.setArrayWithoutId(SolaceOperationBindingModel.Destinations, destinations)
}

parseBindingVersion(binding, SolaceOperationBindingModel.BindingVersion, map)

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

binding
}

private def parseDestination(binding: SolaceOperationBinding, map: YMap)(implicit
ctx: AsyncWebApiContext
): SolaceOperationDestination = {
val destination = SolaceOperationDestination(Annotations())
map.key("destinationType", SolaceOperationDestinationModel.DestinationType in destination)

map.key("deliveryMode") match { // todo validate that it can only be 'direct' or 'persistent'
case Some(value) => Some(value).foreach(SolaceOperationDestinationModel.DeliveryMode in destination)
case None => setDefaultValue(destination, SolaceOperationDestinationModel.DeliveryMode, AmfScalar("persistent"))
}

parseQueue(destination, map)
parseTopic(destination, map)

destination
}

private def parseQueue(destination: SolaceOperationDestination, map: YMap)(implicit ctx: AsyncWebApiContext): Unit = {
map.key(
"queue",
{ entry =>
val queue = SolaceOperationQueue(Annotations(entry.value))
val queueMap = entry.value.as[YMap]

queueMap.key("name", SolaceOperationQueueModel.Name in queue)

queueMap.key("topicSubscriptions", SolaceOperationQueueModel.TopicSubscriptions in queue)

queueMap.key("accessType", SolaceOperationQueueModel.AccessType in queue)
queueMap.key("maxMsgSpoolSize", SolaceOperationQueueModel.MaxMsgSpoolSize in queue)
queueMap.key("maxTtl", SolaceOperationQueueModel.MaxTtl in queue)

ctx.closedShape(queue, queueMap, "SolaceOperationQueue")

destination.setWithoutId(SolaceOperationDestinationModel.Queue, queue, Annotations(entry))
}
)
}

private def parseTopic(destination: SolaceOperationDestination, map: YMap)(implicit ctx: AsyncWebApiContext): Unit = {
map.key(
"topic",
{ entry =>
val topic = SolaceOperationTopic(Annotations(entry.value))
val topicMap = entry.value.as[YMap]

topicMap.key("topicSubscriptions", SolaceOperationTopicModel.TopicSubscriptions in topic)

ctx.closedShape(topic, topicMap, "SolaceOperationTopic")

destination.setWithoutId(SolaceOperationDestinationModel.Topic, topic, Annotations(entry))
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package amf.apicontract.internal.spec.async.parser.bindings.server

import amf.apicontract.client.scala.model.domain.bindings.solace.SolaceServerBinding
import amf.apicontract.internal.metamodel.domain.bindings.SolaceServerBindingModel
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 SolaceServerBindingParser extends BindingParser[SolaceServerBinding] {
override def parse(entry: YMapEntry, parent: String)(implicit ctx: AsyncWebApiContext): SolaceServerBinding = {
val binding = SolaceServerBinding(Annotations(entry))
val map = entry.value.as[YMap]

map.key("msgVpn", SolaceServerBindingModel.MsgVpn in binding)

parseBindingVersion(binding, SolaceServerBindingModel.BindingVersion, map)

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

binding
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object AsyncValidBindingSet {
val async20: AsyncValidBindingSet = AsyncValidBindingSet(basic)
val async21: AsyncValidBindingSet = async20.add(Mercure, IBMMQ)
val async22: AsyncValidBindingSet = async21.add(AnypointMQ)
val async23: AsyncValidBindingSet = async22
val async23: AsyncValidBindingSet = async22.add(Solace)
val async24: AsyncValidBindingSet = async23
val async25: AsyncValidBindingSet = async24
val async26: AsyncValidBindingSet = async25
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
package amf.apicontract.internal.spec.async.parser.context.syntax

import amf.apicontract.internal.spec.async.parser.bindings.Bindings.Solace
import amf.shapes.internal.spec.common.parser.SpecSyntax

object Async23Syntax extends SpecSyntax {
override val nodes: Map[String, Set[String]] = Async22Syntax.nodes
override val nodes: Map[String, Set[String]] =
add(
Async22Syntax.nodes,
"bindings" -> Set(Solace),
"SolaceServerBinding" -> Set(
"msgVpn",
"bindingVersion"
),
"SolaceOperationBinding" -> Set(
"destinations",
"bindingVersion"
),
"SolaceOperationDestination" -> Set(
"destinationType",
"deliveryMode",
"queue",
"topic"
),
"SolaceOperationQueue" -> Set(
"name",
"topicSubscriptions",
"accessType",
"maxMsgSpoolSize",
"maxTtl"
),
"SolaceOperationTopic" -> Set(
"topicSubscriptions"
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
asyncapi: 2.3.0
info:
title: test solace binding
version: 1.0.0
servers:
theName:
url: some.com
protocol: solace
bindings:
solace:
msgVpn: test
bindingVersion: 1.2.3
thisKeyIsNotAllowed: should throw validation error
channels:
some-channel:
publish:
bindings:
solace:
bindingVersion: 0.3.0
destinations:
- destinationType: queue
queue:
name: CreatedHREvents
thisKeyIsNotAllowed: should throw validation error
topicSubscriptions:
- person/*/created
- destinationType: topic
topic:
thisKeyIsNotAllowed: should throw validation error
topicSubscriptions:
- person/*/updated
thisKeyIsNotAllowed: should throw validation error
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
ModelId: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml
Profile:
Conforms: false
Number of results: 4

Level: Violation

- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape
Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.3 SolaceServerBinding node
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml#/async-api/server/some.com/server-bindings/bindings/solace-server
Property:
Range: [(13,8)-(14,0)]
Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml

- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape
Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.3 SolaceOperationQueue node
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml#/async-api/endpoint/some-channel/supportedOperation/publish/operation-bindings/bindings/solace-operation/destinations/solace-destination/solace-queue
Property:
Range: [(24,16)-(25,0)]
Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml

- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape
Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.3 SolaceOperationTopic node
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml#/async-api/endpoint/some-channel/supportedOperation/publish/operation-bindings/bindings/solace-operation/destinations/solace-destination_1/solace-topic
Property:
Range: [(29,16)-(30,0)]
Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml

- Constraint: http://a.ml/vocabularies/amf/parser#closed-shape
Message: Property 'thisKeyIsNotAllowed' not supported in a ASYNC 2.3 SolaceOperationBinding node
Severity: Violation
Target: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml#/async-api/endpoint/some-channel/supportedOperation/publish/operation-bindings/bindings/solace-operation
Property:
Range: [(32,10)-(32,60)]
Location: file://amf-cli/shared/src/test/resources/validations/async20/validations/solace-binding-extra-key.yaml
Loading

0 comments on commit 82eb262

Please sign in to comment.