-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathAsyncApiDocumentDeserializer.cs
More file actions
170 lines (149 loc) · 7.36 KB
/
AsyncApiDocumentDeserializer.cs
File metadata and controls
170 lines (149 loc) · 7.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
namespace ByteBard.AsyncAPI.Readers
{
using ByteBard.AsyncAPI.Extensions;
using ByteBard.AsyncAPI.Models;
using ByteBard.AsyncAPI.Readers.ParseNodes;
using System.Collections.Generic;
using System.Linq;
internal static partial class AsyncApiV2Deserializer
{
private static FixedFieldMap<AsyncApiDocument> asyncApiFixedFields = new()
{
{ "asyncapi", (a, n) => { a.Asyncapi = "2.6.0"; } },
{ "id", (a, n) => a.Id = n.GetScalarValue() },
{ "info", (a, n) => a.Info = LoadInfo(n) },
{ "components", (a, n) => a.Components = LoadComponents(n) }, // Load before anything else so upgrading can go smoothly.
{ "servers", (a, n) => a.Servers = n.CreateMap(LoadServer) },
{ "defaultContentType", (a, n) => a.DefaultContentType = n.GetScalarValue() },
{ "channels", (a, n) => a.Channels = n.CreateMap(key => NormalizeChannelKey(key, n), (n2, originalKey) => LoadChannel(n2, channelAddress: originalKey)) },
{ "tags", (a, n) => a.Info.Tags = n.CreateList(LoadTag) },
{ "externalDocs", (a, n) => a.Info.ExternalDocs = LoadExternalDocs(n) },
};
private static PatternFieldMap<AsyncApiDocument> asyncApiPatternFields = new()
{
{ s => s.StartsWith("x-"), (a, p, n) => a.AddExtension(p, LoadExtension(p, n)) },
};
private static void SetSecuritySchemeScopes(ParsingContext context, AsyncApiDocument document)
{
if (document.Components?.SecuritySchemes == null)
{ return; }
foreach (var securityScheme in document.Components?.SecuritySchemes)
{
var scopes = context.GetFromTempStorage<List<string>>(TempStorageKeys.SecuritySchemeScopes, securityScheme.Key);
if (scopes == null)
{
return;
}
foreach (var scope in scopes)
{
securityScheme.Value.Scopes.Add(scope);
}
}
}
public static AsyncApiDocument LoadAsyncApi(RootNode rootNode)
{
var document = new AsyncApiDocument();
var asyncApiNode = rootNode.GetMap();
ParseMap(asyncApiNode, document, asyncApiFixedFields, asyncApiPatternFields);
asyncApiNode.Context.Workspace.RegisterComponents(document);
SetSecuritySchemeScopes(asyncApiNode.Context, document);
SetMessages(asyncApiNode.Context, document);
SetOperations(asyncApiNode.Context, document);
SetParameters(asyncApiNode.Context, document);
return document;
}
private static void SetParameters(ParsingContext context, AsyncApiDocument document)
{
var parameterReferences =
context.GetFromTempStorage<Dictionary<AsyncApiParameter, AsyncApiJsonSchemaReference>>(TempStorageKeys
.ParameterSchemaReferences);
if (parameterReferences == null)
{
return;
}
foreach (var parameterReference in parameterReferences)
{
var parameter = parameterReference.Key;
var multiFormatSchema = context.Workspace.ResolveReference<AsyncApiMultiFormatSchema>(parameterReference.Value.Reference);
var schema = multiFormatSchema.Schema.As<AsyncApiJsonSchema>();
if (schema == null)
{
continue;
}
if (schema.Enum.Any())
{
parameter.Enum = schema.Enum.Select(e => e.GetValue<string>()).ToList();
}
if (schema.Default != null)
{
parameter.Default = schema.Default.GetValue<string>();
}
if (schema.Examples.Any())
{
parameter.Examples = schema.Examples.Select(e => e.GetValue<string>()).ToList();
}
}
}
private static void SetMessages(ParsingContext context, AsyncApiDocument document)
{
var messages = context.GetFromTempStorage<Dictionary<string, AsyncApiMessage>>(TempStorageKeys.ComponentMessages);
if (messages == null)
{
return;
}
foreach (var message in messages)
{
document?.Components?.Messages.Add(message.Key, message.Value);
}
}
private static void SetOperations(ParsingContext context, AsyncApiDocument document)
{
var operations = context.GetFromTempStorage<Dictionary<string, AsyncApiOperation>>(TempStorageKeys.Operations);
if (operations == null)
{
return;
}
foreach (var operation in operations)
{
document.Operations.Add(operation);
if (operation.Value.Channel != null)
{
var messages = context.GetFromTempStorage<Dictionary<string, AsyncApiMessageReference>>(TempStorageKeys.OperationMessageReferences, operation.Value);
var operationChannelFragmentKey = operation.Value.Channel.Reference.Reference.Split('/').Last();
var channel = document.Channels.FirstOrDefault(channel => channel.Key == operationChannelFragmentKey);
if (channel.Value == null)
{
// it most likely came from a components channel, so the reference will be wrong.
// Find the channel that references this operations channel, and move the reference.
var correctChannelReference = document.Channels.FirstOrDefault(channel => channel.Value is AsyncApiChannelReference reference && reference.Reference.Reference.EndsWith(operationChannelFragmentKey));
if (correctChannelReference.Key != null)
{
operation.Value.Channel = new AsyncApiChannelReference("#/channels/" + correctChannelReference.Key);
channel = correctChannelReference;
}
else
{
continue;
}
}
if (channel.Value is AsyncApiChannelReference channelReference)
{
channelReference.Reference.Workspace = context.Workspace;
// Set reference address to the key, as key in v2 is the address of v3.
var addresses = context.GetFromTempStorage<Dictionary<string, string>>(TempStorageKeys.ChannelAddresses) ?? new Dictionary<string, string>();
channelReference.Address = addresses.GetValueOrDefault(channel.Key) ?? channel.Key;
}
if (messages == null)
{
continue;
}
foreach (var message in messages)
{
channel.Value.Messages.TryAdd(message.Key, message.Value);
operation.Value.Messages.Add(new AsyncApiMessageReference($"#/channels/{channel.Key}/messages/{message.Key}"));
}
}
}
}
}
}