Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

W-15633239 - AvroSchemaDocument ref handle #2025

Merged
merged 2 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package amf.apicontract.internal.spec.async
import amf.apicontract.internal.spec.async.AsyncHeader._
import amf.apicontract.internal.spec.async.parser.context.{Async2WebApiContext, AsyncWebApiContext}
import amf.apicontract.internal.spec.async.parser.document
import amf.apicontract.internal.spec.avro.AvroParsePlugin
import amf.apicontract.internal.spec.common.AsyncWebApiDeclarations
import amf.apicontract.internal.spec.oas.OasLikeParsePlugin
import amf.apicontract.internal.spec.raml.Raml10ParsePlugin
Expand All @@ -20,7 +21,7 @@ object Async20ParsePlugin extends OasLikeParsePlugin {
override def applies(element: Root): Boolean = AsyncHeader(element).isDefined

override def validSpecsToReference: Seq[Spec] =
super.validSpecsToReference :+ Raml10ParsePlugin.spec
super.validSpecsToReference ++ Seq(Raml10ParsePlugin.spec, AvroParsePlugin.spec)

override def mediaTypes: Seq[String] = Seq(Mimes.`application/yaml`, Mimes.`application/json`)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,38 +59,42 @@ case class AsyncApiTypeParser(entry: YMapEntry, adopt: Shape => Unit, version: S
) {

def parse(): Option[Shape] = version match {
case RAML10SchemaVersion => CustomRamlReferenceParser(YMapEntryLike(entry), adopt).parse()
case AVROSchema(_) =>
new AvroShapeParser(YMapEntryLike(entry).asMap)(new AvroSchemaContext(ctx, AvroSettings)).parse()
case _ => OasTypeParser(entry, adopt, version).parse()
case RAML10SchemaVersion => CustomReferenceParser(YMapEntryLike(entry), parseRamlType, adopt).parse()
case AVROSchema(_) => CustomReferenceParser(YMapEntryLike(entry), parseAvroSchema, adopt).parse()
case _ => OasTypeParser(entry, adopt, version).parse()
}

private def parseRamlType(entry: YMapEntryLike): Option[Shape] = {
val context = toRaml(ctx)
context.declarations.shapes = Map.empty
val result =
Raml10TypeParser(entry, "schema", adopt, TypeInfo(), AnyDefaultType)(context).parse()
context.futureDeclarations.resolve()
result
}

private def parseAvroSchema(entry: YMapEntryLike): Option[Shape] = {
new AvroShapeParser(entry.asMap)(new AvroSchemaContext(ctx, AvroSettings)).parse()
}
}

case class CustomRamlReferenceParser(entry: YMapEntryLike, adopt: Shape => Unit)(implicit
val ctx: OasLikeWebApiContext
case class CustomReferenceParser(entry: YMapEntryLike, parser: YMapEntryLike => Option[Shape], adopt: Shape => Unit)(
implicit val ctx: OasLikeWebApiContext
) {

def parse(): Option[Shape] = {
val shape = ctx.link(entry.value) match {
case Left(refValue) => handleRef(refValue)
case Right(_) => parseRamlType(entry)
case Right(_) => parser(entry)
}
shape.foreach(_.annotations += DefinedBySpec(Raml10))
shape
}

private def parseRamlType(entry: YMapEntryLike): Option[Shape] = {
val context = toRaml(ctx)
context.declarations.shapes = Map.empty
val result =
Raml10TypeParser(entry, "schema", adopt, TypeInfo(), AnyDefaultType)(context).parse()
context.futureDeclarations.resolve()
result
}

private def handleRef(refValue: String): Option[Shape] = {
val link = dataTypeFragmentRef(refValue)
.orElse(typeDefinedInLibraryRef(refValue))
.orElse(avroSchemaDocRef(refValue))
.orElse(externalFragmentRef(refValue))

if (link.isEmpty)
Expand All @@ -109,6 +113,11 @@ case class CustomRamlReferenceParser(entry: YMapEntryLike, adopt: Shape => Unit)
result
}

private def avroSchemaDocRef(refValue: String): Option[Shape] = {
val result = ctx.declarations.findEncodedTypeInDocFragment(refValue)
result.map(linkAndAdopt(_, refValue))
}

private def typeDefinedInLibraryRef(refValue: String): Option[Shape] = {
val values = refValue.split("#/types/").toList
values match {
Expand All @@ -122,7 +131,7 @@ case class CustomRamlReferenceParser(entry: YMapEntryLike, adopt: Shape => Unit)

private def externalFragmentRef(refValue: String): Option[Shape] = {
ctx.obtainRemoteYNode(refValue).flatMap { node =>
parseRamlType(YMapEntryLike(node))
parser(YMapEntryLike(node))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import amf.core.client.scala.parse.document._
import amf.core.internal.annotations.{Aliases, ReferencedInfo}
import amf.core.internal.parser.{Root, YMapOps}
import amf.core.internal.validation.CoreValidations.ExpectedModule
import amf.shapes.client.scala.model.document.JsonSchemaDocument
import amf.shapes.client.scala.model.document.{AvroSchemaDocument, JsonSchemaDocument}
import amf.shapes.internal.spec.common.parser.{CommonReferencesParser, ReferencesRegister}
import org.mulesoft.common.collections.FilterType
import org.yaml.model.{YMap, YScalar, YType}
Expand All @@ -24,6 +24,8 @@ case class WebApiRegister()(implicit ctx: WebApiContext) extends ReferencesRegis
module.declares.foreach(declarations += _)
}
case fragment: Fragment => ctx.declarations += (alias, fragment)
case avroDoc: AvroSchemaDocument =>
ctx.declarations.documentFragments += (alias -> (avroDoc.encodes -> Map())) // AVRO Document has no declarations, so it is always an empty Map
case jsonDoc: JsonSchemaDocument =>
ctx.declarations.documentFragments += (alias -> (jsonDoc.encodes -> buildDeclarationMap(jsonDoc)))
case _ => // ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
asyncapi: 2.0.0
info:
title: My API
version: '1.0.0'
channels:
myChannel:
publish:
message:
schemaFormat: application/vnd.apache.avro;version=1.9.0
payload:
$ref: '../schemas/schema-1.9.0.avsc'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
asyncapi: 2.0.0
info:
title: My API
version: '1.0.0'
channels:
myChannel:
publish:
message:
schemaFormat: application/vnd.apache.avro;version=1.9.0
payload:
$ref: '../schemas/schema-1.9.0.json'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
asyncapi: 2.0.0
info:
title: My API
version: '1.0.0'
channels:
myChannel:
publish:
message:
schemaFormat: application/vnd.apache.avro;version=1.9.0
payload:
$ref: '../schemas/schema-1.9.0.json#/fields'
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#%RAML 1.0
title: Some API
/anEndpoint:
get:
responses:
200:
body:
application/json:
type: !include ../schemas/schema-1.9.0.json
Loading