Skip to content
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 @@ -40,7 +40,7 @@ public override void SerializeProperties(IAsyncApiWriter writer)
protected override FixedFieldMap<HttpMessageBinding> FixedFieldMap => new()
{
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
{ "headers", (a, n) => { a.Headers = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "headers", (a, n) => { a.Headers = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public override void SerializeProperties(IAsyncApiWriter writer)
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
{ "type", (a, n) => { a.Type = n.GetScalarValue().GetEnumFromDisplayName<HttpOperationType>(); } },
{ "method", (a, n) => { a.Method = n.GetScalarValue(); } },
{ "query", (a, n) => { a.Query = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "query", (a, n) => { a.Query = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
};

public override string BindingKey => "http";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public override void SerializeProperties(IAsyncApiWriter writer)
protected override FixedFieldMap<KafkaMessageBinding> FixedFieldMap => new()
{
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
{ "key", (a, n) => { a.Key = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "key", (a, n) => { a.Key = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
{ "schemaIdLocation", (a, n) => { a.SchemaIdLocation = n.GetScalarValue(); } },
{ "schemaIdPayloadEncoding", (a, n) => { a.SchemaIdPayloadEncoding = n.GetScalarValue(); } },
{ "schemaLookupStrategy", (a, n) => { a.SchemaLookupStrategy = n.GetScalarValue(); } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public class KafkaOperationBinding : OperationBinding<KafkaOperationBinding>
protected override FixedFieldMap<KafkaOperationBinding> FixedFieldMap => new()
{
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
{ "groupId", (a, n) => { a.GroupId = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "clientId", (a, n) => { a.ClientId = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "groupId", (a, n) => { a.GroupId = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
{ "clientId", (a, n) => { a.ClientId = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override void SerializeProperties(IAsyncApiWriter writer)
protected override FixedFieldMap<MQTTMessageBinding> FixedFieldMap => new()
{
{ "payloadFormatIndicator", (a, n) => { a.PayloadFormatIndicator = n.GetIntegerValueOrDefault(); } },
{ "correlationData", (a, n) => { a.CorrelationData = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "correlationData", (a, n) => { a.CorrelationData = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
{ "contentType", (a, n) => { a.ContentType = n.GetScalarValue(); } },
{ "responseTopic", (a, n) => { a.ResponseTopic = n.GetScalarValue(); } },
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public class WebSocketsChannelBinding : ChannelBinding<WebSocketsChannelBinding>
{
{ "bindingVersion", (a, n) => { a.BindingVersion = n.GetScalarValue(); } },
{ "method", (a, n) => { a.Method = n.GetScalarValue(); } },
{ "query", (a, n) => { a.Query = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "headers", (a, n) => { a.Headers = AsyncApiSchemaDeserializer.LoadSchema(n); } },
{ "query", (a, n) => { a.Query = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
{ "headers", (a, n) => { a.Headers = AsyncApiJsonSchemaDeserializer.LoadSchema(n); } },
};

public override void SerializeProperties(IAsyncApiWriter writer)
Expand Down
3 changes: 3 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public AsyncApiDocument Read(JsonNode input, out AsyncApiDiagnostic diagnostic)
ChannelBindingParsers = this.settings.Bindings.OfType<IBindingParser<IChannelBinding>>().ToDictionary(b => b.BindingKey, b => b),
OperationBindingParsers = this.settings.Bindings.OfType<IBindingParser<IOperationBinding>>().ToDictionary(b => b.BindingKey, b => b),
MessageBindingParsers = this.settings.Bindings.OfType<IBindingParser<IMessageBinding>>().ToDictionary(b => b.BindingKey, b => b),
SchemaParserRegistry = this.settings.SchemaParserRegistry,
};

AsyncApiDocument document = null;
Expand Down Expand Up @@ -90,6 +91,7 @@ public async Task<ReadResult> ReadAsync(JsonNode input, CancellationToken cancel
ChannelBindingParsers = this.settings.Bindings.OfType<IBindingParser<IChannelBinding>>().ToDictionary(b => b.BindingKey, b => b),
OperationBindingParsers = this.settings.Bindings.OfType<IBindingParser<IOperationBinding>>().ToDictionary(b => b.BindingKey, b => b),
MessageBindingParsers = this.settings.Bindings.OfType<IBindingParser<IMessageBinding>>().ToDictionary(b => b.BindingKey, b => b),
SchemaParserRegistry = this.settings.SchemaParserRegistry,
};

AsyncApiDocument document = null;
Expand Down Expand Up @@ -144,6 +146,7 @@ public T ReadFragment<T>(JsonNode input, AsyncApiVersion version, out AsyncApiDi
ChannelBindingParsers = this.settings.Bindings.OfType<IBindingParser<IChannelBinding>>().ToDictionary(b => b.BindingKey, b => b),
OperationBindingParsers = this.settings.Bindings.OfType<IBindingParser<IOperationBinding>>().ToDictionary(b => b.BindingKey, b => b),
MessageBindingParsers = this.settings.Bindings.OfType<IBindingParser<IMessageBinding>>().ToDictionary(b => b.BindingKey, b => b),
SchemaParserRegistry = this.settings.SchemaParserRegistry,
};

IAsyncApiElement element = null;
Expand Down
3 changes: 3 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/AsyncApiReaderSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace ByteBard.AsyncAPI.Readers
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using ByteBard.AsyncAPI.Models;
using ByteBard.AsyncAPI.Models.Interfaces;
using ByteBard.AsyncAPI.Readers.Interface;
Expand Down Expand Up @@ -56,6 +57,8 @@ public ICollection<IBindingParser<IBinding>>
{ get; set; } =
new List<IBindingParser<IBinding>>();

public SchemaParserRegistry SchemaParserRegistry { get; } = new SchemaParserRegistry();

/// <summary>
/// Rules to use for validating AsyncApi specification. If none are provided a default set of rules are applied.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/ParsingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ internal Dictionary<string, Func<AsyncApiAny, IAsyncApiExtension>> ExtensionPars
internal Dictionary<string, IBindingParser<IOperationBinding>> OperationBindingParsers { get; set; } = new();

internal Dictionary<string, IBindingParser<IMessageBinding>> MessageBindingParsers { get; set; } = new();

internal SchemaParserRegistry SchemaParserRegistry { get; set; } = new();

internal RootNode RootNode { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace ByteBard.AsyncAPI.Readers
using ByteBard.AsyncAPI.Models;
using ByteBard.AsyncAPI.Readers.ParseNodes;

public class AsyncApiSchemaDeserializer
public class AsyncApiJsonSchemaDeserializer
{
private static readonly FixedFieldMap<AsyncApiJsonSchema> schemaFixedFields = new()
{
Expand Down
22 changes: 22 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/Schemas/AvroSchemaParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace ByteBard.AsyncAPI.Readers;

using System.Collections.Generic;
using Models.Interfaces;
using ParseNodes;

public class AvroSchemaParser : IAsyncApiSchemaParser
{
public IAsyncApiSchema LoadSchema(ParseNode parseNode)
{
return AsyncApiAvroSchemaDeserializer.LoadSchema(parseNode);
}

public IEnumerable<string> SupportedFormats => new List<string>
{
"application/vnd.apache.avro",
"application/vnd.apache.avro+json",
"application/vnd.apache.avro+yaml",
"application/vnd.apache.avro+json;version=1.9.0",
"application/vnd.apache.avro+yaml;version=1.9.0",
};
}
11 changes: 11 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/Schemas/ISchemaParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ByteBard.AsyncAPI.Readers;

using System.Collections.Generic;
using Models.Interfaces;
using ParseNodes;

public interface IAsyncApiSchemaParser
{
IAsyncApiSchema LoadSchema(ParseNode node);
IEnumerable<string> SupportedFormats { get; }
}
22 changes: 22 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/Schemas/JsonSchemaParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace ByteBard.AsyncAPI.Readers;

using System.Collections.Generic;
using Models.Interfaces;
using ParseNodes;

public class JsonSchemaParser: IAsyncApiSchemaParser
{
public IAsyncApiSchema LoadSchema(ParseNode node)
{
return AsyncApiJsonSchemaDeserializer.LoadSchema(node);
}

public IEnumerable<string> SupportedFormats => new List<string>
{
"application/vnd.aai.asyncapi",
"application/vnd.aai.asyncapi+json",
"application/vnd.aai.asyncapi+yaml",
"application/schema+json;version=draft-07",
"application/schema+yaml;version=draft-07",
};
}
51 changes: 51 additions & 0 deletions src/ByteBard.AsyncAPI.Readers/Schemas/SchemaParserRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
namespace ByteBard.AsyncAPI.Readers;

using System.Collections.Generic;
using System.Linq;

public class SchemaParserRegistry
{
public SchemaParserRegistry()
{
this.RegisterParser(new JsonSchemaParser());
this.RegisterParser(new AvroSchemaParser());
}

private readonly Dictionary<string, IAsyncApiSchemaParser> parsers = new();
private readonly Dictionary<string, string> formatToPrefix = new();

public void RegisterParser(IAsyncApiSchemaParser deserializer)
{
foreach (var format in deserializer.SupportedFormats)
{
this.parsers[format] = deserializer;
this.formatToPrefix[format] = format;
}
}

public IAsyncApiSchemaParser GetParser(string format)
{
if (string.IsNullOrEmpty(format))
{
return this.parsers.Values.FirstOrDefault(d => d is JsonSchemaParser);
}

if (this.parsers.TryGetValue(format, out var parser))
{
return parser;
}

var matchingPrefix = this.formatToPrefix.Keys.FirstOrDefault(prefix => format.StartsWith(prefix));
if (matchingPrefix != null)
{
return this.parsers[matchingPrefix];
}

return null;
}

public IEnumerable<string> GetSupportedFormats()
{
return this.parsers.Keys;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private static AsyncApiMultiFormatSchema LoadMultiSchemaFormat(ParseNode node)
{
var schemas = new AsyncApiMultiFormatSchema
{
Schema = AsyncApiSchemaDeserializer.LoadSchema(node),
Schema = AsyncApiJsonSchemaDeserializer.LoadSchema(node),
};

return schemas;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private static IAsyncApiSchema LoadPayload(ParseNode n, string format)
case null:
case "":
case var _ when SupportedJsonSchemaFormats.Where(s => format.StartsWith(s)).Any():
return AsyncApiSchemaDeserializer.LoadSchema(n);
return AsyncApiJsonSchemaDeserializer.LoadSchema(n);
case var _ when SupportedAvroSchemaFormats.Where(s => format.StartsWith(s)).Any():
return AsyncApiAvroSchemaDeserializer.LoadSchema(n);
default:
Expand Down Expand Up @@ -143,7 +143,7 @@ public static AsyncApiMessage LoadMessage(ParseNode node)

if (mapNode["headers"] != null)
{
message.Headers = new AsyncApiMultiFormatSchema { Schema = AsyncApiSchemaDeserializer.LoadSchema(mapNode["headers"].Value) };
message.Headers = new AsyncApiMultiFormatSchema { Schema = AsyncApiJsonSchemaDeserializer.LoadSchema(mapNode["headers"].Value) };
}

if (mapNode["payload"] != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class AsyncApiV2Deserializer
{
private static FixedFieldMap<AsyncApiMessageTrait> messageTraitFixedFields = new()
{
{ "headers", (a, n) => { a.Headers = new AsyncApiMultiFormatSchema { Schema = AsyncApiSchemaDeserializer.LoadSchema(n) }; } },
{ "headers", (a, n) => { a.Headers = new AsyncApiMultiFormatSchema { Schema = AsyncApiJsonSchemaDeserializer.LoadSchema(n) }; } },
{ "correlationId", (a, n) => { a.CorrelationId = LoadCorrelationId(n); } },
{ "schemaFormat", (a, n) => { a.Headers.SchemaFormat = n.GetScalarValue(); } },
{ "contentType", (a, n) => { a.ContentType = n.GetScalarValue(); } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal static partial class AsyncApiV2Deserializer

private static void LoadParameterFromSchema(AsyncApiParameter instance, ParseNode node)
{
var schema = AsyncApiSchemaDeserializer.LoadSchema(node);
var schema = AsyncApiJsonSchemaDeserializer.LoadSchema(node);
if (schema.Enum.Any())
{
instance.Enum = schema.Enum.Select(e => e.GetValue<string>()).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public AsyncApiV2VersionService(AsyncApiDiagnostic diagnostic)
[typeof(AsyncApiOAuthFlows)] = AsyncApiV2Deserializer.LoadOAuthFlows,
[typeof(AsyncApiOperation)] = AsyncApiV2Deserializer.LoadOperation,
[typeof(AsyncApiParameter)] = AsyncApiV2Deserializer.LoadParameter,
[typeof(AsyncApiJsonSchema)] = AsyncApiSchemaDeserializer.LoadSchema,
[typeof(AsyncApiJsonSchema)] = AsyncApiJsonSchemaDeserializer.LoadSchema,
[typeof(AsyncApiAvroSchema)] = AsyncApiAvroSchemaDeserializer.LoadSchema,
[typeof(AsyncApiJsonSchema)] = AsyncApiV2Deserializer.LoadJsonSchemaPayload,
[typeof(AsyncApiAvroSchema)] = AsyncApiV2Deserializer.LoadAvroPayload,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,60 +31,27 @@ public static AsyncApiMultiFormatSchema LoadMultiFormatSchema(ParseNode node)

var format = mapNode["schemaFormat"].Value.GetScalarValue();
var schema = mapNode["schema"].Value;
schemaFormat.Schema = LoadSchema(schema, LoadSchemaFormat(format));
schemaFormat.Schema = LoadSchema(schema, format);
schemaFormat.SchemaFormat = format;
return schemaFormat;

}

private static IAsyncApiSchema LoadSchema(ParseNode n, string format)
{
if (n == null)
{
return null;
}

switch (format)
{
case null:
case "":
case var _ when SupportedJsonSchemaFormats.Where(s => format.StartsWith(s)).Any():
return AsyncApiSchemaDeserializer.LoadSchema(n);
case var _ when SupportedAvroSchemaFormats.Where(s => format.StartsWith(s)).Any():
return AsyncApiAvroSchemaDeserializer.LoadSchema(n);
default:
var supportedFormats = SupportedJsonSchemaFormats.Concat(SupportedAvroSchemaFormats);
throw new AsyncApiException($"Could not deserialize Schema. Supported formats are {string.Join(", ", supportedFormats)}");
}
}

static readonly IEnumerable<string> SupportedJsonSchemaFormats = new List<string>
{
"application/vnd.aai.asyncapi+json",
"application/vnd.aai.asyncapi+yaml",
"application/vnd.aai.asyncapi",
"application/schema+json;version=draft-07",
"application/schema+yaml;version=draft-07",
};

static readonly IEnumerable<string> SupportedAvroSchemaFormats = new List<string>
{
"application/vnd.apache.avro",
"application/vnd.apache.avro+json",
"application/vnd.apache.avro+yaml",
"application/vnd.apache.avro+json;version=1.9.0",
"application/vnd.apache.avro+yaml;version=1.9.0",
};

private static string LoadSchemaFormat(string schemaFormat)
{
var supportedFormats = SupportedJsonSchemaFormats.Concat(SupportedAvroSchemaFormats);
if (!supportedFormats.Where(s => schemaFormat.StartsWith(s)).Any())
var registry = n.Context.SchemaParserRegistry;
var parser = registry.GetParser(format);
if (parser != null)
{
throw new AsyncApiException($"'{schemaFormat}' is not a supported format. Supported formats are {string.Join(", ", supportedFormats)}");
return parser.LoadSchema(n);
}

return schemaFormat;
var supportedFormats = registry.GetSupportedFormats();
throw new AsyncApiException($"Could not deserialize Schema. Supported formats are {string.Join(", ", supportedFormats)}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal static partial class AsyncApiV3Deserializer

private static void LoadParameterFromSchema(AsyncApiParameter instance, ParseNode node)
{
var schema = AsyncApiSchemaDeserializer.LoadSchema(node);
var schema = AsyncApiJsonSchemaDeserializer.LoadSchema(node);
if (schema.Enum.Any())
{
instance.Enum = schema.Enum.Select(e => e.GetValue<string>()).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public AsyncApiV3VersionService(AsyncApiDiagnostic diagnostic)
[typeof(AsyncApiOperationReply)] = AsyncApiV3Deserializer.LoadOperationReply,
[typeof(AsyncApiOperationReplyAddress)] = AsyncApiV3Deserializer.LoadOperationReplyAddress,
[typeof(AsyncApiParameter)] = AsyncApiV3Deserializer.LoadParameter,
[typeof(AsyncApiJsonSchema)] = AsyncApiSchemaDeserializer.LoadSchema,
[typeof(AsyncApiJsonSchema)] = AsyncApiJsonSchemaDeserializer.LoadSchema,
[typeof(AsyncApiAvroSchema)] = AsyncApiAvroSchemaDeserializer.LoadSchema,
[typeof(AsyncApiSecurityScheme)] = AsyncApiV3Deserializer.LoadSecurityScheme,
[typeof(AsyncApiMultiFormatSchema)] = AsyncApiV3Deserializer.LoadMultiFormatSchema,
Expand Down
Loading
Loading