1
- // Copyright (c) Microsoft Corporation. All rights reserved.
1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
2
// Licensed under the MIT license.
3
3
4
4
using System ;
29
29
using Microsoft . OpenApi . Hidi . Utilities ;
30
30
using Microsoft . OpenApi . Models ;
31
31
using Microsoft . OpenApi . OData ;
32
+ using Microsoft . OpenApi . Reader ;
32
33
using Microsoft . OpenApi . Readers ;
33
34
using Microsoft . OpenApi . Services ;
34
35
using Microsoft . OpenApi . Writers ;
@@ -38,6 +39,12 @@ namespace Microsoft.OpenApi.Hidi
38
39
{
39
40
internal static class OpenApiService
40
41
{
42
+ static OpenApiService ( )
43
+ {
44
+ OpenApiReaderRegistry . RegisterReader ( OpenApiConstants . Yaml , new OpenApiYamlReader ( ) ) ;
45
+ OpenApiReaderRegistry . RegisterReader ( OpenApiConstants . Yml , new OpenApiYamlReader ( ) ) ;
46
+ }
47
+
41
48
/// <summary>
42
49
/// Implementation of the transform command
43
50
/// </summary>
@@ -52,7 +59,10 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l
52
59
{
53
60
if ( options . Output == null )
54
61
{
55
- var inputExtension = GetInputPathExtension ( options . OpenApi , options . Csdl ) ;
62
+ #pragma warning disable CA1308 // Normalize strings to uppercase
63
+ var inputExtension = string . Concat ( "." , options . OpenApiFormat ? . GetDisplayName ( ) . ToLowerInvariant ( ) )
64
+ ?? GetInputPathExtension ( options . OpenApi , options . Csdl ) ;
65
+ #pragma warning restore CA1308 // Normalize strings to uppercase
56
66
options . Output = new ( $ "./output{ inputExtension } ") ;
57
67
} ;
58
68
@@ -85,7 +95,8 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l
85
95
}
86
96
87
97
// Load OpenAPI document
88
- var document = await GetOpenApi ( options , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
98
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
99
+ var document = await GetOpenApi ( options , format , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
89
100
90
101
if ( options . FilterOptions != null )
91
102
{
@@ -212,7 +223,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma
212
223
}
213
224
214
225
// Get OpenAPI document either from OpenAPI or CSDL
215
- private static async Task < OpenApiDocument > GetOpenApi ( HidiOptions options , ILogger logger , string ? metadataVersion = null , CancellationToken cancellationToken = default )
226
+ private static async Task < OpenApiDocument > GetOpenApi ( HidiOptions options , string format , ILogger logger , string ? metadataVersion = null , CancellationToken cancellationToken = default )
216
227
{
217
228
OpenApiDocument document ;
218
229
Stream stream ;
@@ -233,7 +244,7 @@ private static async Task<OpenApiDocument> GetOpenApi(HidiOptions options, ILogg
233
244
await stream . DisposeAsync ( ) . ConfigureAwait ( false ) ;
234
245
}
235
246
236
- document = await ConvertCsdlToOpenApi ( filteredStream ?? stream , metadataVersion , options . SettingsConfig , cancellationToken ) . ConfigureAwait ( false ) ;
247
+ document = await ConvertCsdlToOpenApi ( filteredStream ?? stream , format , metadataVersion , options . SettingsConfig , cancellationToken ) . ConfigureAwait ( false ) ;
237
248
stopwatch . Stop ( ) ;
238
249
logger . LogTrace ( "{Timestamp}ms: Generated OpenAPI with {Paths} paths." , stopwatch . ElapsedMilliseconds , document . Paths . Count ) ;
239
250
}
@@ -368,14 +379,16 @@ private static async Task<ReadResult> ParseOpenApi(string openApiFile, bool inli
368
379
{
369
380
stopwatch . Start ( ) ;
370
381
371
- result = await new OpenApiStreamReader ( new ( )
372
- {
382
+ var settings = new OpenApiReaderSettings
383
+ {
373
384
LoadExternalRefs = inlineExternal ,
374
385
BaseUrl = openApiFile . StartsWith ( "http" , StringComparison . OrdinalIgnoreCase ) ?
375
386
new ( openApiFile ) :
376
387
new Uri ( "file://" + new FileInfo ( openApiFile ) . DirectoryName + Path . DirectorySeparatorChar )
377
- }
378
- ) . ReadAsync ( stream , cancellationToken ) . ConfigureAwait ( false ) ;
388
+ } ;
389
+
390
+ var format = OpenApiModelFactory . GetFormat ( openApiFile ) ;
391
+ result = await OpenApiDocument . LoadAsync ( stream , format , settings , cancellationToken ) . ConfigureAwait ( false ) ;
379
392
380
393
logger . LogTrace ( "{Timestamp}ms: Completed parsing." , stopwatch . ElapsedMilliseconds ) ;
381
394
@@ -391,15 +404,15 @@ private static async Task<ReadResult> ParseOpenApi(string openApiFile, bool inli
391
404
/// </summary>
392
405
/// <param name="csdl">The CSDL stream.</param>
393
406
/// <returns>An OpenAPI document.</returns>
394
- public static async Task < OpenApiDocument > ConvertCsdlToOpenApi ( Stream csdl , string ? metadataVersion = null , IConfiguration ? settings = null , CancellationToken token = default )
407
+ public static async Task < OpenApiDocument > ConvertCsdlToOpenApi ( Stream csdl , string format , string ? metadataVersion = null , IConfiguration ? settings = null , CancellationToken token = default )
395
408
{
396
409
using var reader = new StreamReader ( csdl ) ;
397
410
var csdlText = await reader . ReadToEndAsync ( token ) . ConfigureAwait ( false ) ;
398
411
var edmModel = CsdlReader . Parse ( XElement . Parse ( csdlText ) . CreateReader ( ) ) ;
399
412
settings ??= SettingsUtilities . GetConfiguration ( ) ;
400
413
401
414
var document = edmModel . ConvertToOpenApi ( SettingsUtilities . GetOpenApiConvertSettings ( settings , metadataVersion ) ) ;
402
- document = FixReferences ( document ) ;
415
+ document = FixReferences ( document , format ) ;
403
416
404
417
return document ;
405
418
}
@@ -409,14 +422,15 @@ public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl, stri
409
422
/// </summary>
410
423
/// <param name="document"> The converted OpenApiDocument.</param>
411
424
/// <returns> A valid OpenApiDocument instance.</returns>
412
- public static OpenApiDocument FixReferences ( OpenApiDocument document )
425
+ public static OpenApiDocument FixReferences ( OpenApiDocument document , string format )
413
426
{
414
427
// This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
415
428
// So we write it out, and read it back in again to fix it up.
416
429
417
430
var sb = new StringBuilder ( ) ;
418
431
document . SerializeAsV3 ( new OpenApiYamlWriter ( new StringWriter ( sb ) ) ) ;
419
- var doc = new OpenApiStringReader ( ) . Read ( sb . ToString ( ) , out _ ) ;
432
+
433
+ var doc = OpenApiDocument . Parse ( sb . ToString ( ) , format ) . OpenApiDocument ;
420
434
421
435
return doc ;
422
436
}
@@ -564,7 +578,8 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl
564
578
throw new ArgumentException ( "Please input a file path or URL" ) ;
565
579
}
566
580
567
- var document = await GetOpenApi ( options , logger , null , cancellationToken ) . ConfigureAwait ( false ) ;
581
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
582
+ var document = await GetOpenApi ( options , format , logger , null , cancellationToken ) . ConfigureAwait ( false ) ;
568
583
569
584
using ( logger . BeginScope ( "Creating diagram" ) )
570
585
{
@@ -725,7 +740,8 @@ internal static async Task PluginManifest(HidiOptions options, ILogger logger, C
725
740
}
726
741
727
742
// Load OpenAPI document
728
- var document = await GetOpenApi ( options , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
743
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
744
+ var document = await GetOpenApi ( options , format , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
729
745
730
746
cancellationToken . ThrowIfCancellationRequested ( ) ;
731
747
0 commit comments