From dcaec118bdce2e9faaaf960fa5eab337d17d715d Mon Sep 17 00:00:00 2001 From: arielmirra Date: Mon, 22 Jul 2024 11:06:42 -0300 Subject: [PATCH] W-15633231: add AVRO basic resolution pipelines --- .../client/scala/AMFConfiguration.scala | 18 +++++++++-- .../AvroSchemaEditingPipeline.scala | 30 ++++++++++++++++++ .../AvroSchemaTransformationPipeline.scala | 31 +++++++++++++++++++ .../validation/model/APIRawValidations.scala | 10 ++++-- 4 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaEditingPipeline.scala create mode 100644 amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaTransformationPipeline.scala diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/AMFConfiguration.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/AMFConfiguration.scala index c57440fab4..d6b64adf38 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/AMFConfiguration.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/client/scala/AMFConfiguration.scala @@ -8,6 +8,11 @@ import amf.apicontract.internal.convert.ApiRegister import amf.apicontract.internal.entities.{APIEntities, FragmentEntities} import amf.apicontract.internal.plugins.ApiContractFallbackPlugin import amf.apicontract.internal.spec.async.{Async20ElementRenderPlugin, Async20ParsePlugin, Async20RenderPlugin} +import amf.apicontract.internal.spec.avro.transformation.{ + AvroSchemaCachePipeline, + AvroSchemaEditingPipeline, + AvroSchemaTransformationPipeline +} import amf.apicontract.internal.spec.avro.AvroParsePlugin import amf.apicontract.internal.spec.oas._ import amf.apicontract.internal.spec.raml._ @@ -159,8 +164,17 @@ object RAMLConfiguration extends APIConfigurationBuilder { // AVRO is in alpha support mode object AvroConfiguration extends APIConfigurationBuilder { - def Avro(): AMFConfiguration = - common().withPlugins(List(AvroParsePlugin)) // TODO: add validation profiles and serialization + def Avro(): AMFConfiguration = { + common() + .withPlugins(List(AvroParsePlugin)) // TODO: add validation profiles and serialization + .withTransformationPipelines( + List( + AvroSchemaTransformationPipeline(), + AvroSchemaEditingPipeline(), + AvroSchemaCachePipeline() + ) + ) + } } /** [[APIConfigurationBuilder.common common()]] configuration with all configurations needed for OAS like: diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaEditingPipeline.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaEditingPipeline.scala new file mode 100644 index 0000000000..6469115cab --- /dev/null +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaEditingPipeline.scala @@ -0,0 +1,30 @@ +package amf.apicontract.internal.spec.avro.transformation + +import amf.core.client.common.transform._ +import amf.core.client.common.validation.ProfileNames.AVROSCHEMA +import amf.core.client.scala.transform.{TransformationPipeline, TransformationStep} +import amf.core.internal.transform.stages.{ReferenceResolutionStage, SourceInformationStage, UrlShortenerStage} +import amf.shapes.internal.domain.resolution.ShapeNormalizationForUnitStage + +class AvroSchemaEditingPipeline private (urlShortening: Boolean = true, val name: String) + extends TransformationPipeline { + + private def url: Option[UrlShortenerStage] = if (urlShortening) Some(new UrlShortenerStage()) else None + + override def steps: Seq[TransformationStep] = Seq() +// Seq( +// new ReferenceResolutionStage(true), +// new ShapeNormalizationForUnitStage(AVROSCHEMA, keepEditingInfo = true) +// ) ++ url :+ SourceInformationStage +} + +object AvroSchemaEditingPipeline { + def apply() = new AvroSchemaEditingPipeline(true, name) + private[amf] def cachePipeline = new AvroSchemaEditingPipeline(false, PipelineId.Editing) + val name: String = PipelineId.Editing +} + +object AvroSchemaCachePipeline { + val name: String = PipelineId.Cache + private[amf] def apply(): AvroSchemaEditingPipeline = AvroSchemaEditingPipeline.cachePipeline +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaTransformationPipeline.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaTransformationPipeline.scala new file mode 100644 index 0000000000..93b2fe4937 --- /dev/null +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/spec/avro/transformation/AvroSchemaTransformationPipeline.scala @@ -0,0 +1,31 @@ +package amf.apicontract.internal.spec.avro.transformation + +import amf.core.client.common.transform.PipelineId +import amf.core.client.common.validation.AvroSchemaProfile +import amf.core.client.scala.transform.{TransformationPipeline, TransformationStep} +import amf.core.internal.transform.stages.{ + CleanReferencesStage, + ExternalSourceRemovalStage, + ReferenceResolutionStage, + SourceInformationStage +} +import amf.shapes.internal.domain.resolution.ShapeNormalizationForUnitStage + +class AvroSchemaTransformationPipeline private (override val name: String) extends TransformationPipeline() { + def references = new ReferenceResolutionStage(false) + + // in theory we don't need any transformation step, but i'll leave here the common ones + override def steps: Seq[TransformationStep] = + Seq( +// references, +// new ExternalSourceRemovalStage, +// new ShapeNormalizationForUnitStage(AvroSchemaProfile, keepEditingInfo = false), +// new CleanReferencesStage(), +// SourceInformationStage + ) +} + +object AvroSchemaTransformationPipeline { + def apply() = new AvroSchemaTransformationPipeline(name) + val name: String = PipelineId.Default +} diff --git a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/validation/model/APIRawValidations.scala b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/validation/model/APIRawValidations.scala index 62016d1d46..b4a67f2e4c 100644 --- a/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/validation/model/APIRawValidations.scala +++ b/amf-api-contract/shared/src/main/scala/amf/apicontract/internal/validation/model/APIRawValidations.scala @@ -1220,14 +1220,16 @@ object APIRawValidations extends CommonValidationDefinitions { value = "direct,persistent" ), AMFValidation( - message = "Invalid 'maxMsgSpoolSize' value. It should be a string representing the maximum size of the message spool.", + message = + "Invalid 'maxMsgSpoolSize' value. It should be a string representing the maximum size of the message spool.", owlClass = apiBinding("SolaceOperationQueue030"), owlProperty = apiBinding("maxMsgSpoolSize"), constraint = sh("datatype"), value = "xsd:string" ), AMFValidation( - message = "Invalid 'maxMsgSpoolSize' value. It should be a string representing the maximum size of the message spool.", + message = + "Invalid 'maxMsgSpoolSize' value. It should be a string representing the maximum size of the message spool.", owlClass = apiBinding("SolaceOperationQueue040"), owlProperty = apiBinding("maxMsgSpoolSize"), constraint = sh("datatype"), @@ -1672,7 +1674,8 @@ object APIRawValidations extends CommonValidationDefinitions { Oas20Profile -> forProfile(Oas20Profile), Oas30Profile -> forProfile(Oas30Profile), Async20Profile -> forProfile(Async20Profile), - JsonSchemaProfile -> forProfile(JsonSchemaProfile) + JsonSchemaProfile -> forProfile(JsonSchemaProfile), + AvroSchemaProfile -> forProfile(AvroSchemaProfile) ) override def forProfile(p: ProfileName): ProfileValidations = { @@ -1683,6 +1686,7 @@ object APIRawValidations extends CommonValidationDefinitions { case Oas30Profile => Oas30Validations case Async20Profile => Async20Validations case JsonSchemaProfile => ShapeValidations + case AvroSchemaProfile => ShapeValidations // todo: should we do ShapeValidations? case AmfProfile => AmfValidations case _ => () => Seq.empty