diff --git a/src/LEGO.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs b/src/LEGO.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs index 5c0826af..fbce6668 100644 --- a/src/LEGO.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs +++ b/src/LEGO.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) The LEGO Group. All rights reserved. +// Copyright (c) The LEGO Group. All rights reserved. namespace LEGO.AsyncAPI.Readers { @@ -63,12 +63,12 @@ public AsyncApiDocument Read(JsonNode input, out AsyncApiDiagnostic diagnostic) if (this.settings.RuleSet != null && this.settings.RuleSet.Rules.Count > 0) { var asyncApiErrors = document.Validate(this.settings.RuleSet); - foreach (var item in asyncApiErrors.Where(e => e is AsyncApiValidatorError)) + foreach (var item in asyncApiErrors.OfType()) { diagnostic.Errors.Add(item); } - foreach (var item in asyncApiErrors.Where(e => e is AsyncApiValidatorWarning)) + foreach (var item in asyncApiErrors.OfType()) { diagnostic.Warnings.Add(item); } @@ -100,11 +100,16 @@ public async Task ReadAsync(JsonNode input, CancellationToken cancel // Validate the document if (this.settings.RuleSet != null && this.settings.RuleSet.Rules.Count > 0) { - var errors = document.Validate(this.settings.RuleSet); - foreach (var item in errors) + var asyncApiErrors = document.Validate(this.settings.RuleSet); + foreach (var item in asyncApiErrors.OfType()) { diagnostic.Errors.Add(item); } + + foreach (var item in asyncApiErrors.OfType()) + { + diagnostic.Warnings.Add(item); + } } return new ReadResult diff --git a/src/LEGO.AsyncAPI.Readers/AsyncApiStreamReader.cs b/src/LEGO.AsyncAPI.Readers/AsyncApiStreamReader.cs index aeaf33c0..2cbf47ac 100644 --- a/src/LEGO.AsyncAPI.Readers/AsyncApiStreamReader.cs +++ b/src/LEGO.AsyncAPI.Readers/AsyncApiStreamReader.cs @@ -3,6 +3,7 @@ namespace LEGO.AsyncAPI.Readers { using System.IO; + using System.Threading; using System.Threading.Tasks; using LEGO.AsyncAPI.Models; using LEGO.AsyncAPI.Models.Interfaces; @@ -46,8 +47,11 @@ public AsyncApiDocument Read(Stream input, out AsyncApiDiagnostic diagnostic) /// Reads the stream input and parses it into an AsyncApi document. /// /// Stream containing AsyncApi description to parse. - /// Instance result containing newly created AsyncApiDocument and diagnostics object from the process. - public async Task ReadAsync(Stream input) + /// The cancellation token. + /// + /// Instance result containing newly created AsyncApiDocument and diagnostics object from the process. + /// + public async Task ReadAsync(Stream input, CancellationToken cancellationToken) { MemoryStream bufferedStream; if (input is MemoryStream) @@ -65,7 +69,7 @@ public async Task ReadAsync(Stream input) var reader = new StreamReader(bufferedStream); - return await new AsyncApiTextReader(this.settings).ReadAsync(reader); + return await new AsyncApiTextReader(this.settings).ReadAsync(reader, cancellationToken); } /// diff --git a/src/LEGO.AsyncAPI.Readers/AsyncApiTextReader.cs b/src/LEGO.AsyncAPI.Readers/AsyncApiTextReader.cs index 3299a6a6..64587e46 100644 --- a/src/LEGO.AsyncAPI.Readers/AsyncApiTextReader.cs +++ b/src/LEGO.AsyncAPI.Readers/AsyncApiTextReader.cs @@ -6,6 +6,7 @@ namespace LEGO.AsyncAPI.Readers using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; + using System.Threading; using System.Threading.Tasks; using LEGO.AsyncAPI.Models; using LEGO.AsyncAPI.Models.Interfaces; @@ -57,8 +58,11 @@ public AsyncApiDocument Read(TextReader input, out AsyncApiDiagnostic diagnostic /// Reads the content of the TextReader. /// /// TextReader containing AsyncApi description to parse. - /// A ReadResult instance that contains the resulting AsyncApiDocument and a diagnostics instance. - public async Task ReadAsync(TextReader input) + /// The cancellation token. + /// + /// A ReadResult instance that contains the resulting AsyncApiDocument and a diagnostics instance. + /// + public async Task ReadAsync(TextReader input, CancellationToken cancellationToken) { JsonNode jsonNode; @@ -78,7 +82,7 @@ public async Task ReadAsync(TextReader input) }; } - return await new AsyncApiJsonDocumentReader(this.settings).ReadAsync(jsonNode); + return await new AsyncApiJsonDocumentReader(this.settings).ReadAsync(jsonNode, cancellationToken); } /// diff --git a/src/LEGO.AsyncAPI.Readers/V2/AsyncApiV2VersionService.cs b/src/LEGO.AsyncAPI.Readers/V2/AsyncApiV2VersionService.cs index 42562d9a..3c99409c 100644 --- a/src/LEGO.AsyncAPI.Readers/V2/AsyncApiV2VersionService.cs +++ b/src/LEGO.AsyncAPI.Readers/V2/AsyncApiV2VersionService.cs @@ -54,78 +54,81 @@ public AsyncApiReference ConvertToAsyncApiReference( string reference, ReferenceType? type) { - if (!string.IsNullOrWhiteSpace(reference)) + if (string.IsNullOrWhiteSpace(reference)) { - var segments = reference.Split('#'); - if (segments.Length == 1) + throw new AsyncApiException($"The reference string '{reference}' has invalid format."); + } + + var segments = reference.Split('#'); + if (segments.Length == 1) + { + if (type == ReferenceType.SecurityScheme) { - if (type == ReferenceType.SecurityScheme) + return new AsyncApiReference { - return new AsyncApiReference - { - Type = type, - Id = reference, - }; - } + Type = type, + Id = reference, + }; + } - var asyncApiReference = new AsyncApiReference(); - if (reference.StartsWith("/")) - { - asyncApiReference.IsFragment = true; - } + var asyncApiReference = new AsyncApiReference(); + asyncApiReference.Type = type; + if (reference.StartsWith("/")) + { + asyncApiReference.IsFragment = true; + } - asyncApiReference.ExternalResource = segments[0]; + asyncApiReference.ExternalResource = segments[0]; - return asyncApiReference; + return asyncApiReference; - } - else if (segments.Length == 2) + } + else if (segments.Length == 2) + { + // Local reference + if (reference.StartsWith("#")) { - // Local reference - if (reference.StartsWith("#")) + try { - try - { - return this.ParseReference(segments[1]); - } - catch (AsyncApiException ex) - { - this.Diagnostic.Errors.Add(new AsyncApiError(ex)); - return null; - } + return this.ParseReference(segments[1]); } - - var id = segments[1]; - var asyncApiReference = new AsyncApiReference(); - if (id.StartsWith("/components/")) + catch (AsyncApiException ex) { - var localSegments = segments[1].Split('/'); - var referencedType = localSegments[2].GetEnumFromDisplayName(); - if (type == null) - { - type = referencedType; - } - else - { - if (type != referencedType) - { - throw new AsyncApiException("Referenced type mismatch"); - } - } + this.Diagnostic.Errors.Add(new AsyncApiError(ex)); + return null; + } + } - id = localSegments[3]; + var id = segments[1]; + var asyncApiReference = new AsyncApiReference(); + if (id.StartsWith("/components/")) + { + var localSegments = segments[1].Split('/'); + var referencedType = localSegments[2].GetEnumFromDisplayName(); + if (type == null) + { + type = referencedType; } else { - asyncApiReference.IsFragment = true; + if (type != referencedType) + { + throw new AsyncApiException("Referenced type mismatch"); + } } - asyncApiReference.ExternalResource = segments[0]; - asyncApiReference.Type = type; - asyncApiReference.Id = id; - - return asyncApiReference; + id = localSegments[3]; } + else + { + asyncApiReference.IsFragment = true; + } + + asyncApiReference.ExternalResource = segments[0]; + asyncApiReference.Type = type; + asyncApiReference.Id = id; + + return asyncApiReference; } throw new AsyncApiException($"The reference string '{reference}' has invalid format."); diff --git a/test/LEGO.AsyncAPI.Tests/Bindings/Http/HttpBindings_Should.cs b/test/LEGO.AsyncAPI.Tests/Bindings/Http/HttpBindings_Should.cs index 0b00bbf7..b207dcd8 100644 --- a/test/LEGO.AsyncAPI.Tests/Bindings/Http/HttpBindings_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Bindings/Http/HttpBindings_Should.cs @@ -36,7 +36,7 @@ public void HttpMessageBinding_FilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Http); + settings.Bindings = BindingsCollection.Http; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -73,7 +73,7 @@ public void HttpOperationBinding_FilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Http); + settings.Bindings = BindingsCollection.Http; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert diff --git a/test/LEGO.AsyncAPI.Tests/Bindings/Kafka/KafkaBindings_Should.cs b/test/LEGO.AsyncAPI.Tests/Bindings/Kafka/KafkaBindings_Should.cs index 537e904c..efeac315 100644 --- a/test/LEGO.AsyncAPI.Tests/Bindings/Kafka/KafkaBindings_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Bindings/Kafka/KafkaBindings_Should.cs @@ -55,7 +55,7 @@ public void KafkaChannelBinding_WithFilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Kafka); + settings.Bindings = BindingsCollection.Kafka; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -92,7 +92,7 @@ public void KafkaServerBinding_WithFilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Kafka); + settings.Bindings = BindingsCollection.Kafka; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -131,7 +131,7 @@ public void KafkaMessageBinding_WithFilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Kafka); + settings.Bindings = BindingsCollection.Kafka; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -171,7 +171,7 @@ public void KafkaOperationBinding_WithFilledObject_SerializesAndDeserializes() expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Kafka); + settings.Bindings = BindingsCollection.Kafka; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert diff --git a/test/LEGO.AsyncAPI.Tests/Bindings/Pulsar/PulsarBindings_Should.cs b/test/LEGO.AsyncAPI.Tests/Bindings/Pulsar/PulsarBindings_Should.cs index 15577763..c99bfa6c 100644 --- a/test/LEGO.AsyncAPI.Tests/Bindings/Pulsar/PulsarBindings_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Bindings/Pulsar/PulsarBindings_Should.cs @@ -61,7 +61,7 @@ public void PulsarChannelBinding_WithFilledObject_SerializesAndDeserializes() expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -80,7 +80,7 @@ public void PulsarChannelBindingNamespaceDefaultToNull() // Act var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -99,7 +99,7 @@ public void PulsarChannelBindingPropertiesExceptNamespaceDefaultToNull() // Act // Assert var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); var pulsarBinding = ((PulsarChannelBinding)binding.Bindings["pulsar"]); @@ -139,7 +139,7 @@ public void PulsarServerBinding_WithFilledObject_SerializesAndDeserializes() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -175,7 +175,7 @@ public void ServerBindingVersionDefaultsToNull() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert @@ -212,7 +212,7 @@ public void ServerTenantDefaultsToNull() actual = actual.MakeLineBreaksEnvironmentNeutral(); expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Pulsar); + settings.Bindings = BindingsCollection.Pulsar; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert diff --git a/test/LEGO.AsyncAPI.Tests/Bindings/WebSockets/WebSocketBindings_Should.cs b/test/LEGO.AsyncAPI.Tests/Bindings/WebSockets/WebSocketBindings_Should.cs index 2a57b997..0e9c5344 100644 --- a/test/LEGO.AsyncAPI.Tests/Bindings/WebSockets/WebSocketBindings_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Bindings/WebSockets/WebSocketBindings_Should.cs @@ -44,7 +44,7 @@ public void WebSocketChannelBinding_WithFilledObject_SerializesAndDeserializes() expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.Websockets); + settings.Bindings = BindingsCollection.Websockets; var binding = new AsyncApiStringReader(settings).ReadFragment(actual, AsyncApiVersion.AsyncApi2_0, out _); // Assert diff --git a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiMessage_Should.cs b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiMessage_Should.cs index a9207f92..cc4b7aa7 100644 --- a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiMessage_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiMessage_Should.cs @@ -393,7 +393,7 @@ public void AsyncApiMessage_WithFilledObject_Serializes() expected = expected.MakeLineBreaksEnvironmentNeutral(); var settings = new AsyncApiReaderSettings(); - settings.Bindings.Add(BindingsCollection.All); + settings.Bindings = BindingsCollection.All; var deserializedMessage = new AsyncApiStringReader(settings).ReadFragment(expected, AsyncApiVersion.AsyncApi2_0, out _); // Assert diff --git a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiReference_Should.cs b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiReference_Should.cs index 34831e86..273162b3 100644 --- a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiReference_Should.cs +++ b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiReference_Should.cs @@ -31,7 +31,7 @@ public void AsyncApiReference_WithExternalFragmentUriReference_AllowReference() reference.Id.Should().Be("/path/to/external/fragment"); reference.IsFragment.Should().BeTrue(); reference.IsExternal.Should().BeTrue(); - + reference.Type.Should().Be(ReferenceType.Schema); var serialized = deserialized.SerializeAsYaml(AsyncApiVersion.AsyncApi2_0); actual = actual.MakeLineBreaksEnvironmentNeutral(); var expected = serialized.MakeLineBreaksEnvironmentNeutral(); @@ -54,6 +54,7 @@ public void AsyncApiReference_WithFragmentReference_AllowReference() deserialized.Payload.UnresolvedReference.Should().BeTrue(); var reference = deserialized.Payload.Reference; + reference.Type.Should().Be(ReferenceType.Schema); reference.ExternalResource.Should().Be("/fragments/myFragment"); reference.Id.Should().BeNull(); reference.IsFragment.Should().BeTrue(); @@ -206,10 +207,10 @@ public void AsyncApiDocument_WithExternalReference_DoesNotResolve() channel.UnresolvedReference.Should().BeTrue(); channel.Description.Should().BeNull(); channel.Reference.ExternalResource.Should().Be("http://example.com/channel.json"); + channel.Reference.Type.Should().Be(ReferenceType.Channel); channel.Reference.Id.Should().BeNull(); channel.Reference.IsExternal.Should().BeTrue(); channel.Reference.IsFragment.Should().BeFalse(); - channel.Reference.Type.Should().BeNull(); } [Test]