Skip to content

Commit

Permalink
W-12689958: add Solace binding emission
Browse files Browse the repository at this point in the history
  • Loading branch information
arielmirra committed Mar 14, 2024
1 parent 82eb262 commit 4d3ab82
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,32 @@ import amf.apicontract.client.scala.model.domain.bindings.amqp.Amqp091OperationB
import amf.apicontract.client.scala.model.domain.bindings.http.HttpOperationBinding
import amf.apicontract.client.scala.model.domain.bindings.kafka.KafkaOperationBinding
import amf.apicontract.client.scala.model.domain.bindings.mqtt.MqttOperationBinding
import amf.apicontract.client.scala.model.domain.bindings.solace.{
SolaceOperationBinding,
SolaceOperationDestination,
SolaceOperationQueue,
SolaceOperationTopic
}
import amf.apicontract.internal.metamodel.domain.bindings.{
Amqp091OperationBindingModel,
HttpOperationBindingModel,
KafkaOperationBindingModel,
MqttOperationBindingModel
MqttOperationBindingModel,
SolaceOperationBindingModel,
SolaceOperationQueueModel,
SolaceOperationTopicModel
}
import amf.apicontract.internal.spec.async.emitters.domain
import amf.apicontract.internal.spec.async.emitters.domain.AsyncApiDestinationsEmitter
import amf.apicontract.internal.spec.async.parser.bindings.Bindings.Solace
import amf.apicontract.internal.spec.oas.emitter.context.OasLikeSpecEmitterContext
import org.mulesoft.common.client.lexical.Position
import amf.core.client.scala.model.domain.Shape
import amf.core.internal.render.BaseEmitters.{ValueEmitter, pos, traverse}
import amf.core.internal.render.SpecOrdering
import amf.core.internal.render.emitters.EntryEmitter
import org.yaml.model.{YDocument, YNode}
import org.yaml.model.YDocument.EntryBuilder
import org.yaml.model.{YDocument, YMap, YNode}

import scala.collection.mutable.ListBuffer

Expand All @@ -35,6 +47,7 @@ class AsyncApiOperationBindingsEmitter(binding: OperationBinding, ordering: Spec
case binding: HttpOperationBinding => Some(new HttpOperationBindingEmitter(binding, ordering))
case binding: KafkaOperationBinding => Some(new KafkaOperationBindingEmitter(binding, ordering))
case binding: MqttOperationBinding => Some(new MqttOperationBindingEmitter(binding, ordering))
case binding: SolaceOperationBinding => Some(new SolaceOperationBindingEmitter(binding, ordering))
case _ => None
}

Expand Down Expand Up @@ -140,3 +153,27 @@ class Amqp091OperationBindingEmitter(binding: Amqp091OperationBinding, ordering:

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

class SolaceOperationBindingEmitter(binding: SolaceOperationBinding, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends AsyncApiCommonBindingEmitter {

override def emit(b: YDocument.EntryBuilder): Unit = {
b.entry(
YNode(Solace),
_.obj { emitter =>
val result = ListBuffer[EntryEmitter]()
val fs = binding.fields

fs.entry(SolaceOperationBindingModel.Destinations)
.foreach(f => result += AsyncApiDestinationsEmitter(f, ordering))

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 @@ -7,11 +7,13 @@ import amf.core.internal.render.emitters.EntryEmitter
import amf.apicontract.internal.metamodel.domain.bindings.{
IBMMQServerBindingModel,
MqttServerBindingModel,
MqttServerLastWillModel
MqttServerLastWillModel,
SolaceServerBindingModel
}
import amf.apicontract.client.scala.model.domain.bindings.ServerBinding
import amf.apicontract.client.scala.model.domain.bindings.ibmmq.IBMMQServerBinding
import amf.apicontract.client.scala.model.domain.bindings.mqtt.{MqttServerBinding, MqttServerLastWill}
import amf.apicontract.client.scala.model.domain.bindings.solace.SolaceServerBinding
import amf.apicontract.internal.spec.async.parser.bindings.Bindings._
import amf.apicontract.internal.spec.oas.emitter.context.OasLikeSpecEmitterContext
import org.yaml.model.{YDocument, YNode}
Expand All @@ -27,9 +29,10 @@ class AsyncApiServerBindingsEmitter(binding: ServerBinding, ordering: SpecOrderi
}

private def emitterFor(binding: ServerBinding): Option[EntryEmitter] = binding match {
case binding: MqttServerBinding => Some(new MqttServerBindingEmitter(binding, ordering))
case binding: IBMMQServerBinding => Some(new IBMMQServerBindingEmitter(binding, ordering))
case _ => None
case binding: MqttServerBinding => Some(new MqttServerBindingEmitter(binding, ordering))
case binding: IBMMQServerBinding => Some(new IBMMQServerBindingEmitter(binding, ordering))
case binding: SolaceServerBinding => Some(new SolaceServerBindingEmitter(binding, ordering))
case _ => None
}

override def position(): Position = pos(binding.annotations)
Expand Down Expand Up @@ -108,3 +111,24 @@ class IBMMQServerBindingEmitter(binding: IBMMQServerBinding, ordering: SpecOrder

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

class SolaceServerBindingEmitter(binding: SolaceServerBinding, ordering: SpecOrdering)
extends AsyncApiCommonBindingEmitter {

override def emit(b: YDocument.EntryBuilder): Unit = {
b.entry(
YNode(Solace),
_.obj { emitter =>
val result = ListBuffer[EntryEmitter]()
val fs = binding.fields

fs.entry(SolaceServerBindingModel.MsgVpn).foreach(f => result += ValueEmitter("msgVpn", 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
@@ -0,0 +1,123 @@
package amf.apicontract.internal.spec.async.emitters.domain

import amf.apicontract.client.scala.model.domain.bindings.solace.{
SolaceOperationDestination,
SolaceOperationQueue,
SolaceOperationTopic
}
import amf.apicontract.internal.metamodel.domain.bindings.{
SolaceOperationDestinationModel,
SolaceOperationQueueModel,
SolaceOperationTopicModel
}
import amf.apicontract.internal.spec.common.emitter.AgnosticShapeEmitterContextAdapter
import amf.apicontract.internal.spec.oas.emitter.context.OasLikeSpecEmitterContext
import amf.core.internal.parser.domain.FieldEntry
import amf.core.internal.render.BaseEmitters.{ArrayEmitter, RawEmitter, ValueEmitter, pos, traverse}
import amf.core.internal.render.SpecOrdering
import amf.core.internal.render.emitters.{EntryEmitter, PartEmitter}
import amf.shapes.internal.annotations.OrphanOasExtension
import amf.shapes.internal.spec.common.emitter.annotations.AnnotationsEmitter
import org.mulesoft.common.client.lexical.Position
import org.mulesoft.common.client.lexical.Position.ZERO
import org.yaml.model.YDocument.{EntryBuilder, PartBuilder}
import org.yaml.model.{YDocument, YNode}

import scala.collection.mutable.ListBuffer

case class AsyncApiDestinationsEmitter(f: FieldEntry, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends EntryEmitter {

val key = "destinations"

override def emit(b: YDocument.EntryBuilder): Unit = {
val destinations =
f.array.values
.map(_.asInstanceOf[SolaceOperationDestination])
.map(new SingleDestinationEmitter(_, ordering))

b.entry(
key,
_.list(traverse(destinations, _))
)
}

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

class SingleDestinationEmitter(destination: SolaceOperationDestination, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends PartEmitter {
protected implicit val shapeCtx = AgnosticShapeEmitterContextAdapter(spec)
override def emit(b: YDocument.PartBuilder): Unit = {

val result = ListBuffer[EntryEmitter]()
val fs = destination.fields

fs.entry(SolaceOperationDestinationModel.DestinationType).foreach(f => result += ValueEmitter("destinationType", f))
fs.entry(SolaceOperationDestinationModel.DeliveryMode).foreach { f =>
// in parsing the field may have been added as default value and synthesized, if so we should not emit it
if (!f.value.annotations.isSynthesized) {
result += ValueEmitter("deliveryMode", f)
}
}

Option(destination.queue).foreach(queue => result += new SolaceOperationQueueEmitter(queue, ordering))
Option(destination.topic).foreach(topic => result += new SolaceOperationTopicEmitter(topic, ordering))

result ++= AnnotationsEmitter(destination, ordering).emitters

b.obj(traverse(ordering.sorted(result), _))
}

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

class SolaceOperationQueueEmitter(queue: SolaceOperationQueue, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends EntryEmitter {

override def emit(b: EntryBuilder): Unit = {
b.entry(
YNode("queue"),
_.obj { emitter =>
val result = ListBuffer[EntryEmitter]()
val fs = queue.fields

fs.entry(SolaceOperationQueueModel.Name).foreach(f => result += ValueEmitter("name", f))
fs.entry(SolaceOperationQueueModel.TopicSubscriptions)
.foreach(f => result += spec.arrayEmitter("topicSubscriptions", f, ordering))
fs.entry(SolaceOperationQueueModel.AccessType).foreach(f => result += ValueEmitter("accessType", f))
fs.entry(SolaceOperationQueueModel.MaxMsgSpoolSize).foreach(f => result += ValueEmitter("maxMsgSpoolSize", f))
fs.entry(SolaceOperationQueueModel.MaxTtl).foreach(f => result += ValueEmitter("maxTtl", f))

traverse(ordering.sorted(result), emitter)
}
)
}

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

class SolaceOperationTopicEmitter(topic: SolaceOperationTopic, ordering: SpecOrdering)(implicit
val spec: OasLikeSpecEmitterContext
) extends EntryEmitter {

override def emit(b: EntryBuilder): Unit = {
b.entry(
YNode("topic"),
_.obj { emitter =>
val result = ListBuffer[EntryEmitter]()
val fs = topic.fields

fs.entry(SolaceOperationQueueModel.TopicSubscriptions)
.foreach(f => result += spec.arrayEmitter("topicSubscriptions", f, ordering))

traverse(ordering.sorted(result), emitter)
}
)
}

override def position(): Position = pos(topic.annotations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ trait BindingParser[+Binding <: DomainElement] extends SpecParserOps {
}

protected def setDefaultValue(obj: AmfObject, field: Field, element: AmfElement): obj.type = {
// TODO: if field not explicit in spec we should check for synthesized and not emit it
obj.setWithoutId(field, element, Annotations.synthesized())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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
channels:
some-channel:
publish:
bindings:
solace:
bindingVersion: 0.3.0
destinations:
-
destinationType: queue
queue:
name: CreatedHREvents
accessType: test
maxMsgSpoolSize: test
maxTtl: test
topicSubscriptions:
- person/*/created
-
destinationType: topic
topic:
topicSubscriptions:
- person/*/updated
Loading

0 comments on commit 4d3ab82

Please sign in to comment.