Skip to content

Commit 59260d3

Browse files
authored
Added more comparers (#328)
* Added comparison logic for - OpenApiInfo - OpenApiContact - OpenApiLicense - OpenApiExternalDocs - OpenApiSecurityRequirements - OpenApiTag
1 parent 0c86ee2 commit 59260d3

30 files changed

+3053
-355
lines changed

src/Microsoft.OpenApi/Services/OpenApiComparerBase.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Licensed under the MIT license.
33

44
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
57
using Microsoft.OpenApi.Models;
68

79
namespace Microsoft.OpenApi.Services
@@ -46,6 +48,32 @@ internal void Compare(string source, string target, ComparisonContext comparison
4648
}
4749
}
4850

51+
/// <summary>
52+
/// Compares two Uri object.
53+
/// </summary>
54+
/// <param name="source">The source.</param>
55+
/// <param name="target">The target.</param>
56+
/// <param name="comparisonContext">The context under which to compare the objects.</param>
57+
internal void Compare(Uri source, Uri target, ComparisonContext comparisonContext)
58+
{
59+
if (source == null && target == null)
60+
{
61+
return;
62+
}
63+
64+
if (source != target)
65+
{
66+
comparisonContext.AddOpenApiDifference(new OpenApiDifference
67+
{
68+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Update,
69+
OpenApiComparedElementType = typeof(Uri),
70+
SourceValue = source,
71+
TargetValue = target,
72+
Pointer = comparisonContext.PathString
73+
});
74+
}
75+
}
76+
4977
/// <summary>
5078
/// Compares two boolean object.
5179
/// </summary>
@@ -138,6 +166,67 @@ internal void Compare<TEnum>(Enum source, Enum target, ComparisonContext compari
138166
}
139167
}
140168

169+
/// <summary>
170+
/// Compares <see cref="IDictionary{TKey,TValue}"/> where TKey is <see cref="string"/> and TValue is
171+
/// <see cref="string"/>.
172+
/// </summary>
173+
/// <param name="source">The source.</param>
174+
/// <param name="target">The target.</param>
175+
/// <param name="comparisonContext">The context under which to compare the objects.</param>
176+
internal void Compare(IDictionary<string, string> source, IDictionary<string, string> target,
177+
ComparisonContext comparisonContext)
178+
{
179+
if (source == null && target == null)
180+
{
181+
return;
182+
}
183+
184+
if (source == null || target == null)
185+
{
186+
comparisonContext.AddOpenApiDifference(
187+
new OpenApiDifference
188+
{
189+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Update,
190+
SourceValue = source,
191+
TargetValue = target,
192+
OpenApiComparedElementType = typeof(IDictionary<string, T>),
193+
Pointer = comparisonContext.PathString
194+
});
195+
196+
return;
197+
}
198+
199+
var newKeysInTarget = target.Keys.Except(source.Keys).ToList();
200+
201+
foreach (var newKeyInTarget in newKeysInTarget)
202+
{
203+
WalkAndAddOpenApiDifference(
204+
comparisonContext,
205+
newKeyInTarget,
206+
new OpenApiDifference
207+
{
208+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Add,
209+
TargetValue = target[newKeyInTarget],
210+
OpenApiComparedElementType = typeof(string)
211+
});
212+
}
213+
214+
var removedKeysFromSource = source.Keys.Except(target.Keys).ToList();
215+
216+
foreach (var removedKeyFromSource in removedKeysFromSource)
217+
{
218+
WalkAndAddOpenApiDifference(
219+
comparisonContext,
220+
removedKeyFromSource,
221+
new OpenApiDifference
222+
{
223+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Remove,
224+
SourceValue = source[removedKeyFromSource],
225+
OpenApiComparedElementType = typeof(string)
226+
});
227+
}
228+
}
229+
141230
/// <summary>
142231
/// Adds a segment to the context path to enable pointing to the current location in the document.
143232
/// </summary>

src/Microsoft.OpenApi/Services/OpenApiComparerFactory.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,29 @@ public class OpenApiComparerFactory
3333
{typeof(IDictionary<string, OpenApiParameter>), new OpenApiDictionaryComparer<OpenApiParameter>()},
3434
{typeof(IDictionary<string, OpenApiRequestBody>), new OpenApiDictionaryComparer<OpenApiRequestBody>()},
3535
{typeof(IDictionary<string, OpenApiSchema>), new OpenApiDictionaryComparer<OpenApiSchema>()},
36+
{
37+
typeof(IDictionary<string, OpenApiSecurityScheme>),
38+
new OpenApiDictionaryComparer<OpenApiSecurityScheme>()
39+
},
3640
{typeof(OpenApiHeader), new OpenApiHeaderComparer()},
3741
{typeof(OpenApiRequestBody), new OpenApiRequestBodyComparer()},
3842
{typeof(OpenApiResponse), new OpenApiResponseComparer()},
3943
{typeof(OpenApiComponents), new OpenApiComponentsComparer()},
4044
{typeof(OpenApiEncoding), new OpenApiEncodingComparer()},
4145
{typeof(IList<OpenApiServer>), new OpenApiServersComparer()},
4246
{typeof(OpenApiServer), new OpenApiServerComparer()},
43-
{typeof(OpenApiServerVariable), new OpenApiServerVariableComparer()}
47+
{typeof(OpenApiServerVariable), new OpenApiServerVariableComparer()},
48+
{typeof(OpenApiOAuthFlow), new OpenApiOAuthFlowComparer()},
49+
{typeof(OpenApiOAuthFlows), new OpenApiOAuthFlowsComparer()},
50+
{typeof(OpenApiSecurityRequirement), new OpenApiSecurityRequirementComparer()},
51+
{typeof(OpenApiInfo), new OpenApiInfoComparer()},
52+
{typeof(OpenApiContact), new OpenApiContactComparer()},
53+
{typeof(OpenApiLicense), new OpenApiLicenseComparer()},
54+
{typeof(IList<OpenApiSecurityRequirement>), new OpenApiOrderedListComparer<OpenApiSecurityRequirement>()},
55+
{typeof(IList<OpenApiTag>), new OpenApiOrderedListComparer<OpenApiTag>()},
56+
{typeof(OpenApiExternalDocs), new OpenApiExternalDocsComparer()},
57+
{typeof(OpenApiTag), new OpenApiTagComparer()},
58+
{typeof(OpenApiSecurityScheme), new OpenApiSecuritySchemeComparer()}
4459
};
4560

4661
private readonly Dictionary<Type, object> _typeToComparerMap = new Dictionary<Type, object>();

src/Microsoft.OpenApi/Services/OpenApiComponentsComparer.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,14 @@ public override void Compare(
7777
.GetComparer<IDictionary<string, OpenApiHeader>>()
7878
.Compare(sourceComponents.Headers, targetComponents.Headers, comparisonContext));
7979

80+
WalkAndCompare(
81+
comparisonContext,
82+
OpenApiConstants.SecuritySchemes,
83+
() => comparisonContext
84+
.GetComparer<IDictionary<string, OpenApiSecurityScheme>>()
85+
.Compare(sourceComponents.SecuritySchemes, targetComponents.SecuritySchemes, comparisonContext));
86+
8087
// To Do compare Examples
81-
// To Do compare SecuritySchemes
8288
// To Do compare Links
8389
// To Do compare Callbacks
8490
// To Do compare Extensions
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Models;
5+
6+
namespace Microsoft.OpenApi.Services
7+
{
8+
/// <summary>
9+
/// Defines behavior for comparing properties of <see cref="OpenApiContact"/>.
10+
/// </summary>
11+
public class OpenApiContactComparer : OpenApiComparerBase<OpenApiContact>
12+
{
13+
/// <summary>
14+
/// Executes comparision against source and target <see cref="OpenApiContact"/>.
15+
/// </summary>
16+
/// <param name="sourceContact">The source.</param>
17+
/// <param name="targetContact">The target.</param>
18+
/// <param name="comparisonContext">Context under which to compare the source and target.</param>
19+
public override void Compare(
20+
OpenApiContact sourceContact,
21+
OpenApiContact targetContact,
22+
ComparisonContext comparisonContext)
23+
{
24+
if (sourceContact == null && targetContact == null)
25+
{
26+
return;
27+
}
28+
29+
if (sourceContact == null || targetContact == null)
30+
{
31+
comparisonContext.AddOpenApiDifference(
32+
new OpenApiDifference
33+
{
34+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Update,
35+
SourceValue = sourceContact,
36+
TargetValue = targetContact,
37+
OpenApiComparedElementType = typeof(OpenApiContact),
38+
Pointer = comparisonContext.PathString
39+
});
40+
41+
return;
42+
}
43+
44+
WalkAndCompare(comparisonContext, OpenApiConstants.Name,
45+
() => Compare(sourceContact.Name, targetContact.Name, comparisonContext));
46+
47+
WalkAndCompare(comparisonContext, OpenApiConstants.Email,
48+
() => Compare(sourceContact.Email, targetContact.Email, comparisonContext));
49+
50+
WalkAndCompare(comparisonContext, OpenApiConstants.Url,
51+
() => Compare(sourceContact.Url, targetContact.Url, comparisonContext));
52+
}
53+
}
54+
}

src/Microsoft.OpenApi/Services/OpenApiDictionaryComparer.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,8 @@ public override void Compare(
5656
new OpenApiDifference
5757
{
5858
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Add,
59-
TargetValue = new KeyValuePair<string, T>(
60-
newKeyInTarget,
61-
targetFragment[newKeyInTarget]),
62-
OpenApiComparedElementType = typeof(KeyValuePair<string, T>)
59+
TargetValue = targetFragment[newKeyInTarget],
60+
OpenApiComparedElementType = typeof(T)
6361
});
6462
}
6563

@@ -80,8 +78,8 @@ public override void Compare(
8078
new OpenApiDifference
8179
{
8280
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Remove,
83-
SourceValue = source,
84-
OpenApiComparedElementType = typeof(KeyValuePair<string, T>)
81+
SourceValue = source.Value,
82+
OpenApiComparedElementType = typeof(T)
8583
});
8684
}
8785
}

src/Microsoft.OpenApi/Services/OpenApiDocumentComparer.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,34 @@ public override void Compare(
4343
.GetComparer<IList<OpenApiServer>>()
4444
.Compare(sourceDocument.Servers, targetDocument.Servers, comparisonContext));
4545

46-
// To Do Compare Info
47-
// To Do Compare Security Requirements
48-
// To Do Compare Tags
49-
// To Do Compare External Docs
50-
// To Do Compare Extensions
46+
WalkAndCompare(
47+
comparisonContext,
48+
OpenApiConstants.Info,
49+
() => comparisonContext
50+
.GetComparer<OpenApiInfo>()
51+
.Compare(sourceDocument.Info, targetDocument.Info, comparisonContext));
52+
53+
WalkAndCompare(
54+
comparisonContext,
55+
OpenApiConstants.Security,
56+
() => comparisonContext
57+
.GetComparer<IList<OpenApiSecurityRequirement>>()
58+
.Compare(sourceDocument.SecurityRequirements, targetDocument.SecurityRequirements,
59+
comparisonContext));
60+
61+
WalkAndCompare(
62+
comparisonContext,
63+
OpenApiConstants.Tags,
64+
() => comparisonContext
65+
.GetComparer<IList<OpenApiTag>>()
66+
.Compare(sourceDocument.Tags, targetDocument.Tags, comparisonContext));
67+
68+
WalkAndCompare(
69+
comparisonContext,
70+
OpenApiConstants.ExternalDocs,
71+
() => comparisonContext
72+
.GetComparer<OpenApiExternalDocs>()
73+
.Compare(sourceDocument.ExternalDocs, targetDocument.ExternalDocs, comparisonContext));
5174
}
5275
}
5376
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Models;
5+
6+
namespace Microsoft.OpenApi.Services
7+
{
8+
/// <summary>
9+
/// Defines behavior for comparing properties of <see cref="OpenApiExternalDocs"/>.
10+
/// </summary>
11+
public class OpenApiExternalDocsComparer : OpenApiComparerBase<OpenApiExternalDocs>
12+
{
13+
/// <summary>
14+
/// Executes comparision against source and target <see cref="OpenApiExternalDocs"/>.
15+
/// </summary>
16+
/// <param name="sourceDocs">The source.</param>
17+
/// <param name="targetDocs">The target.</param>
18+
/// <param name="comparisonContext">Context under which to compare the source and target.</param>
19+
public override void Compare(OpenApiExternalDocs sourceDocs, OpenApiExternalDocs targetDocs,
20+
ComparisonContext comparisonContext)
21+
{
22+
if (sourceDocs == null && targetDocs == null)
23+
{
24+
return;
25+
}
26+
27+
if (sourceDocs == null || targetDocs == null)
28+
{
29+
comparisonContext.AddOpenApiDifference(
30+
new OpenApiDifference
31+
{
32+
OpenApiDifferenceOperation = OpenApiDifferenceOperation.Update,
33+
SourceValue = sourceDocs,
34+
TargetValue = targetDocs,
35+
OpenApiComparedElementType = typeof(OpenApiExternalDocs),
36+
Pointer = comparisonContext.PathString
37+
});
38+
return;
39+
}
40+
41+
WalkAndCompare(comparisonContext, OpenApiConstants.Description,
42+
() => Compare(sourceDocs.Description, targetDocs.Description, comparisonContext));
43+
44+
WalkAndCompare(comparisonContext, OpenApiConstants.Url,
45+
() => Compare(sourceDocs.Url, targetDocs.Url, comparisonContext));
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)