1
+ // Copyright (c) Microsoft Corporation. All rights reserved.
2
+ // Licensed under the MIT license.
3
+
4
+ using System ;
5
+ using System . IO ;
6
+ using System . Linq ;
7
+ using Microsoft . OpenApi . Exceptions ;
8
+ using Microsoft . OpenApi . Extensions ;
9
+ using Microsoft . OpenApi . Interfaces ;
10
+ using Microsoft . OpenApi . Models ;
11
+ using Microsoft . OpenApi . Readers . Interface ;
12
+ using Microsoft . OpenApi . Readers . Services ;
13
+ using Microsoft . OpenApi . Services ;
14
+ using SharpYaml . Serialization ;
15
+
16
+ namespace Microsoft . OpenApi . Readers
17
+ {
18
+ /// <summary>
19
+ /// Service class for converting contents of TextReader into OpenApiDocument instances
20
+ /// </summary>
21
+ public class OpenApiYamlDocumentReader : IOpenApiReader < YamlDocument , OpenApiDiagnostic >
22
+ {
23
+ private readonly OpenApiReaderSettings _settings ;
24
+
25
+ /// <summary>
26
+ /// Create stream reader with custom settings if desired.
27
+ /// </summary>
28
+ /// <param name="settings"></param>
29
+ public OpenApiYamlDocumentReader ( OpenApiReaderSettings settings = null )
30
+ {
31
+ _settings = settings ?? new OpenApiReaderSettings ( ) ;
32
+ }
33
+
34
+ /// <summary>
35
+ /// Reads the stream input and parses it into an Open API document.
36
+ /// </summary>
37
+ /// <param name="input">TextReader containing OpenAPI description to parse.</param>
38
+ /// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
39
+ /// <returns>Instance of newly created OpenApiDocument</returns>
40
+ public OpenApiDocument Read ( YamlDocument input , out OpenApiDiagnostic diagnostic )
41
+ {
42
+ diagnostic = new OpenApiDiagnostic ( ) ;
43
+ var context = new ParsingContext
44
+ {
45
+ ExtensionParsers = _settings . ExtensionParsers ,
46
+ BaseUrl = _settings . BaseUrl
47
+ } ;
48
+
49
+ OpenApiDocument document = null ;
50
+ try
51
+ {
52
+ // Parse the OpenAPI Document
53
+ document = context . Parse ( input , diagnostic ) ;
54
+
55
+ // Resolve References if requested
56
+ switch ( _settings . ReferenceResolution )
57
+ {
58
+ case ReferenceResolutionSetting . ResolveAllReferences :
59
+ throw new ArgumentException ( Properties . SRResource . CannotResolveRemoteReferencesSynchronously ) ;
60
+ case ReferenceResolutionSetting . ResolveLocalReferences :
61
+ var resolver = new OpenApiReferenceResolver ( document ) ;
62
+ var walker = new OpenApiWalker ( resolver ) ;
63
+ walker . Walk ( document ) ;
64
+ foreach ( var item in resolver . Errors )
65
+ {
66
+ diagnostic . Errors . Add ( item ) ;
67
+ }
68
+ break ;
69
+ case ReferenceResolutionSetting . DoNotResolveReferences :
70
+ break ;
71
+ }
72
+ }
73
+ catch ( OpenApiException ex )
74
+ {
75
+ diagnostic . Errors . Add ( new OpenApiError ( ex ) ) ;
76
+ }
77
+
78
+ // Validate the document
79
+ if ( _settings . RuleSet != null && _settings . RuleSet . Rules . Count > 0 )
80
+ {
81
+ var errors = document . Validate ( _settings . RuleSet ) ;
82
+ foreach ( var item in errors )
83
+ {
84
+ diagnostic . Errors . Add ( item ) ;
85
+ }
86
+ }
87
+
88
+ return document ;
89
+ }
90
+ /// <summary>
91
+ /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
92
+ /// </summary>
93
+ /// <param name="input">TextReader containing OpenAPI description to parse.</param>
94
+ /// <param name="version">Version of the OpenAPI specification that the fragment conforms to.</param>
95
+ /// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
96
+ /// <returns>Instance of newly created OpenApiDocument</returns>
97
+ public T ReadFragment < T > ( YamlDocument input , OpenApiSpecVersion version , out OpenApiDiagnostic diagnostic ) where T : IOpenApiElement
98
+ {
99
+ diagnostic = new OpenApiDiagnostic ( ) ;
100
+ var context = new ParsingContext
101
+ {
102
+ ExtensionParsers = _settings . ExtensionParsers
103
+ } ;
104
+
105
+ IOpenApiElement element = null ;
106
+ try
107
+ {
108
+ // Parse the OpenAPI element
109
+ element = context . ParseFragment < T > ( input , version , diagnostic ) ;
110
+ }
111
+ catch ( OpenApiException ex )
112
+ {
113
+ diagnostic . Errors . Add ( new OpenApiError ( ex ) ) ;
114
+ }
115
+
116
+ // Validate the element
117
+ if ( _settings . RuleSet != null && _settings . RuleSet . Rules . Count > 0 )
118
+ {
119
+ var errors = element . Validate ( _settings . RuleSet ) ;
120
+ foreach ( var item in errors )
121
+ {
122
+ diagnostic . Errors . Add ( item ) ;
123
+ }
124
+ }
125
+
126
+ return ( T ) element ;
127
+ }
128
+
129
+ /// <summary>
130
+ /// Helper method to turn streams into YamlDocument
131
+ /// </summary>
132
+ /// <param name="input">Stream containing YAML formatted text</param>
133
+ /// <returns>Instance of a YamlDocument</returns>
134
+ static YamlDocument LoadYamlDocument ( TextReader input )
135
+ {
136
+ var yamlStream = new YamlStream ( ) ;
137
+ yamlStream . Load ( input ) ;
138
+ return yamlStream . Documents . First ( ) ;
139
+ }
140
+ }
141
+ }
0 commit comments