Skip to content

Commit 4df5db8

Browse files
OpenApiYamlDocumentReader added
1 parent 83b5d87 commit 4df5db8

File tree

2 files changed

+145
-84
lines changed

2 files changed

+145
-84
lines changed

src/Microsoft.OpenApi.Readers/OpenApiTextReaderReader.cs

Lines changed: 4 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
using System;
54
using System.IO;
65
using System.Linq;
7-
using Microsoft.OpenApi.Exceptions;
8-
using Microsoft.OpenApi.Extensions;
96
using Microsoft.OpenApi.Interfaces;
107
using Microsoft.OpenApi.Models;
118
using Microsoft.OpenApi.Readers.Interface;
12-
using Microsoft.OpenApi.Readers.Services;
13-
using Microsoft.OpenApi.Services;
149
using SharpYaml;
1510
using SharpYaml.Serialization;
1611

@@ -40,9 +35,7 @@ public OpenApiTextReaderReader(OpenApiReaderSettings settings = null)
4035
/// <returns>Instance of newly created OpenApiDocument</returns>
4136
public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
4237
{
43-
ParsingContext context;
4438
YamlDocument yamlDocument;
45-
diagnostic = new OpenApiDiagnostic();
4639

4740
// Parse the YAML/JSON
4841
try
@@ -51,57 +44,12 @@ public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
5144
}
5245
catch (YamlException ex)
5346
{
47+
diagnostic = new OpenApiDiagnostic();
5448
diagnostic.Errors.Add(new OpenApiError($"#char={ex.Start.Line}", ex.Message));
5549
return new OpenApiDocument();
5650
}
5751

58-
context = new ParsingContext
59-
{
60-
ExtensionParsers = _settings.ExtensionParsers,
61-
BaseUrl = _settings.BaseUrl
62-
};
63-
64-
OpenApiDocument document = null;
65-
66-
try
67-
{
68-
// Parse the OpenAPI Document
69-
document = context.Parse(yamlDocument, diagnostic);
70-
71-
// Resolve References if requested
72-
switch (_settings.ReferenceResolution)
73-
{
74-
case ReferenceResolutionSetting.ResolveAllReferences:
75-
throw new ArgumentException(Properties.SRResource.CannotResolveRemoteReferencesSynchronously);
76-
case ReferenceResolutionSetting.ResolveLocalReferences:
77-
var resolver = new OpenApiReferenceResolver(document);
78-
var walker = new OpenApiWalker(resolver);
79-
walker.Walk(document);
80-
foreach (var item in resolver.Errors)
81-
{
82-
diagnostic.Errors.Add(item);
83-
}
84-
break;
85-
case ReferenceResolutionSetting.DoNotResolveReferences:
86-
break;
87-
}
88-
}
89-
catch (OpenApiException ex)
90-
{
91-
diagnostic.Errors.Add(new OpenApiError(ex));
92-
}
93-
94-
// Validate the document
95-
if (_settings.RuleSet != null && _settings.RuleSet.Rules.Count > 0)
96-
{
97-
var errors = document.Validate(_settings.RuleSet);
98-
foreach (var item in errors)
99-
{
100-
diagnostic.Errors.Add(item);
101-
}
102-
}
103-
104-
return document;
52+
return new OpenApiYamlDocumentReader(this._settings).Read(yamlDocument, out diagnostic);
10553
}
10654
/// <summary>
10755
/// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element.
@@ -112,9 +60,7 @@ public OpenApiDocument Read(TextReader input, out OpenApiDiagnostic diagnostic)
11260
/// <returns>Instance of newly created OpenApiDocument</returns>
11361
public T ReadFragment<T>(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic) where T : IOpenApiElement
11462
{
115-
ParsingContext context;
11663
YamlDocument yamlDocument;
117-
diagnostic = new OpenApiDiagnostic();
11864

11965
// Parse the YAML/JSON
12066
try
@@ -123,38 +69,12 @@ public T ReadFragment<T>(TextReader input, OpenApiSpecVersion version, out OpenA
12369
}
12470
catch (YamlException ex)
12571
{
72+
diagnostic = new OpenApiDiagnostic();
12673
diagnostic.Errors.Add(new OpenApiError($"#line={ex.Start.Line}", ex.Message));
12774
return default(T);
12875
}
12976

130-
context = new ParsingContext
131-
{
132-
ExtensionParsers = _settings.ExtensionParsers
133-
};
134-
135-
IOpenApiElement element = null;
136-
137-
try
138-
{
139-
// Parse the OpenAPI element
140-
element = context.ParseFragment<T>(yamlDocument, version, diagnostic);
141-
}
142-
catch (OpenApiException ex)
143-
{
144-
diagnostic.Errors.Add(new OpenApiError(ex));
145-
}
146-
147-
// Validate the element
148-
if (_settings.RuleSet != null && _settings.RuleSet.Rules.Count > 0)
149-
{
150-
var errors = element.Validate(_settings.RuleSet);
151-
foreach (var item in errors)
152-
{
153-
diagnostic.Errors.Add(item);
154-
}
155-
}
156-
157-
return (T)element;
77+
return new OpenApiYamlDocumentReader(this._settings).ReadFragment<T>(yamlDocument, version, out diagnostic);
15878
}
15979

16080
/// <summary>
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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

Comments
 (0)