|
| 1 | +package amf.apicontract.internal.spec.avro.parser.domain |
| 2 | + |
| 3 | +import amf.apicontract.internal.spec.avro.parser.context.AvroSchemaContext |
| 4 | +import amf.core.internal.datanode.DataNodeParser |
| 5 | +import amf.core.internal.metamodel.domain.ShapeModel |
| 6 | +import amf.core.internal.parser.YMapOps |
| 7 | +import amf.core.internal.parser.domain.Annotations |
| 8 | +import amf.shapes.client.scala.model.domain.AnyShape |
| 9 | +import amf.shapes.internal.domain.metamodel.AnyShapeModel |
| 10 | +import amf.shapes.internal.spec.common.parser.QuickFieldParserOps |
| 11 | +import org.yaml.model._ |
| 12 | + |
| 13 | +abstract class AvroComplexShapeParser(map: YMap)(implicit ctx: AvroSchemaContext) |
| 14 | + extends QuickFieldParserOps |
| 15 | + with AvroKeyExtractor { |
| 16 | + val shape: AnyShape |
| 17 | + |
| 18 | + def parse(): AnyShape = { |
| 19 | + addTypeToCache() |
| 20 | + parseCommonFields() |
| 21 | + parseSpecificFields() |
| 22 | + parseDefault() |
| 23 | + shape |
| 24 | + } |
| 25 | + |
| 26 | + def parseCommonFields(): Unit = { |
| 27 | + map.key("name", AnyShapeModel.Name in shape) |
| 28 | + map.key("namespace", (AnyShapeModel.AvroNamespace in shape).allowingAnnotations) |
| 29 | + map.key("aliases", (AnyShapeModel.Aliases in shape).allowingAnnotations) |
| 30 | + map.key("doc", (AnyShapeModel.Description in shape).allowingAnnotations) |
| 31 | + } |
| 32 | + |
| 33 | + // each specific parser should override and parse it's specific fields |
| 34 | + def parseSpecificFields(): Unit |
| 35 | + |
| 36 | + def parseDefault(): Unit = { |
| 37 | + map.key( |
| 38 | + "default", |
| 39 | + entry => { |
| 40 | + val dataNode = DataNodeParser(entry.value).parse() |
| 41 | + shape.set(ShapeModel.Default, dataNode, Annotations(entry)) |
| 42 | + } |
| 43 | + ) |
| 44 | + } |
| 45 | + |
| 46 | + private def addTypeToCache(): Unit = { |
| 47 | + def getText(node: YNode) = node.as[YScalar].text |
| 48 | + def getAliases(entry: YMapEntry): IndexedSeq[String] = entry.value.as[YSequence].nodes.map(getText) |
| 49 | + val name = map.key("name").map(name => getText(name.value)) |
| 50 | + val aliases = map.key("aliases").map(getAliases) |
| 51 | + name.foreach(ctx.globalSpace.put(_, shape)) |
| 52 | + aliases.foreach(_.foreach(alias => ctx.globalSpace.put(alias, shape))) |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +trait AvroKeyExtractor { |
| 57 | + implicit class YMapKeys(map: YMap) { |
| 58 | + def typeValue: Option[YNode] = map.key("type").map(_.value) |
| 59 | + def `type`: Option[String] = typeValue.flatMap(_.asScalar).map(_.text) |
| 60 | + } |
| 61 | + |
| 62 | + implicit class StringAvroOps(value: String) { |
| 63 | + def isPrimitive: Boolean = |
| 64 | + Seq("null", "boolean", "int", "long", "float", "double", "bytes", "string").contains(value) |
| 65 | + } |
| 66 | +} |
0 commit comments