Skip to content

Commit 7d07628

Browse files
committed
async external ref resolution
1 parent 661bfdb commit 7d07628

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

src/LEGO.AsyncAPI.Readers/AsyncApiJsonDocumentReader.cs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public async Task<ReadResult> ReadAsync(JsonNode input, CancellationToken cancel
9999
{
100100
// Parse the AsyncApi Document
101101
document = this.context.Parse(input);
102-
this.ResolveReferences(diagnostic, document);
102+
await this.ResolveReferencesAsync(diagnostic, document);
103103
}
104104
catch (AsyncApiException ex)
105105
{
@@ -172,6 +172,51 @@ public T ReadFragment<T>(JsonNode input, AsyncApiVersion version, out AsyncApiDi
172172
return (T)element;
173173
}
174174

175+
private async Task ResolveReferencesAsync(AsyncApiDiagnostic diagnostic, IAsyncApiSerializable serializable)
176+
{
177+
if (this.settings.ReferenceResolution == ReferenceResolutionSetting.DoNotResolveReferences)
178+
{
179+
return;
180+
}
181+
182+
var collector = new AsyncApiReferenceCollector(this.context.Workspace);
183+
var walker = new AsyncApiWalker(collector);
184+
walker.Walk(serializable);
185+
186+
foreach (var reference in collector.References)
187+
{
188+
if (this.context.Workspace.Contains(reference.Reference.Reference))
189+
{
190+
continue;
191+
}
192+
193+
IAsyncApiSerializable component = null;
194+
if (reference.Reference.IsExternal)
195+
{
196+
if (this.settings.ReferenceResolution != ReferenceResolutionSetting.ResolveAllReferences)
197+
{
198+
continue;
199+
}
200+
201+
component = await this.ResolveExternalReferenceAsync(diagnostic, reference);
202+
}
203+
else
204+
{
205+
var stream = this.context.Workspace.ResolveReference<Stream>(string.Empty); // get whole document.
206+
component = this.ResolveStreamReference(stream, reference, diagnostic);
207+
}
208+
209+
if (component == null)
210+
{
211+
diagnostic.Errors.Add(new AsyncApiError(string.Empty, $"Unable to deserialize reference '{reference.Reference.Reference}'"));
212+
continue;
213+
}
214+
215+
this.context.Workspace.RegisterComponent(reference.Reference.Reference, component);
216+
this.ResolveReferences(diagnostic, component);
217+
}
218+
}
219+
175220
private void ResolveReferences(AsyncApiDiagnostic diagnostic, IAsyncApiSerializable serializable)
176221
{
177222
if (this.settings.ReferenceResolution == ReferenceResolutionSetting.DoNotResolveReferences)
@@ -247,6 +292,36 @@ private IAsyncApiSerializable ResolveExternalReference(AsyncApiDiagnostic diagno
247292
}
248293
}
249294

295+
private async Task<IAsyncApiSerializable> ResolveExternalReferenceAsync(AsyncApiDiagnostic diagnostic, IAsyncApiReferenceable reference)
296+
{
297+
if (reference is null)
298+
{
299+
throw new ArgumentNullException(nameof(reference));
300+
}
301+
302+
var loader = this.settings.ExternalReferenceLoader ??= new DefaultStreamLoader(this.settings);
303+
try
304+
{
305+
Stream stream;
306+
if (this.context.Workspace.Contains(reference.Reference.ExternalResource))
307+
{
308+
stream = this.context.Workspace.ResolveReference<Stream>(reference.Reference.ExternalResource);
309+
}
310+
else
311+
{
312+
stream = await loader.LoadAsync(new Uri(reference.Reference.ExternalResource, UriKind.RelativeOrAbsolute));
313+
this.context.Workspace.RegisterComponent(reference.Reference.ExternalResource, stream);
314+
}
315+
316+
return this.ResolveStreamReference(stream, reference, diagnostic);
317+
}
318+
catch (AsyncApiException ex)
319+
{
320+
diagnostic.Errors.Add(new AsyncApiError(ex));
321+
return null;
322+
}
323+
}
324+
250325
private JsonNode ReadToJson(Stream stream)
251326
{
252327
if (stream != null)

0 commit comments

Comments
 (0)