Skip to content

Commit 376e54d

Browse files
committed
fix: open API link reference proxy design pattern implementation
Signed-off-by: Vincent Biret <[email protected]>
1 parent 0cb4ccb commit 376e54d

18 files changed

+202
-162
lines changed

src/Microsoft.OpenApi.Hidi/StatsVisitor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public override void Visit(OpenApiOperation operation)
6262

6363
public int LinkCount { get; set; }
6464

65-
public override void Visit(OpenApiLink link)
65+
public override void Visit(IOpenApiLink link)
6666
{
6767
LinkCount++;
6868
}

src/Microsoft.OpenApi.Workbench/StatsVisitor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public override void Visit(OpenApiOperation operation)
6262

6363
public int LinkCount { get; set; }
6464

65-
public override void Visit(OpenApiLink link)
65+
public override void Visit(IOpenApiLink link)
6666
{
6767
LinkCount++;
6868
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
using Microsoft.OpenApi.Interfaces;
3+
4+
namespace Microsoft.OpenApi.Models.Interfaces;
5+
6+
/// <summary>
7+
/// Defines the base properties for the link object.
8+
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
9+
/// </summary>
10+
public interface IOpenApiLink : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible
11+
{
12+
/// <summary>
13+
/// A relative or absolute reference to an OAS operation.
14+
/// This field is mutually exclusive of the operationId field, and MUST point to an Operation Object.
15+
/// </summary>
16+
public string OperationRef { get; }
17+
18+
/// <summary>
19+
/// The name of an existing, resolvable OAS operation, as defined with a unique operationId.
20+
/// This field is mutually exclusive of the operationRef field.
21+
/// </summary>
22+
public string OperationId { get; }
23+
24+
/// <summary>
25+
/// A map representing parameters to pass to an operation as specified with operationId or identified via operationRef.
26+
/// </summary>
27+
public IDictionary<string, RuntimeExpressionAnyWrapper> Parameters { get; }
28+
29+
/// <summary>
30+
/// A literal value or {expression} to use as a request body when calling the target operation.
31+
/// </summary>
32+
public RuntimeExpressionAnyWrapper RequestBody { get; }
33+
/// <summary>
34+
/// A server object to be used by the target operation.
35+
/// </summary>
36+
public OpenApiServer Server { get; }
37+
}

src/Microsoft.OpenApi/Models/OpenApiComponents.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible
5656
new Dictionary<string, OpenApiSecurityScheme>();
5757

5858
/// <summary>
59-
/// An object to hold reusable <see cref="OpenApiLink"/> Objects.
59+
/// An object to hold reusable <see cref="IOpenApiLink"/> Objects.
6060
/// </summary>
61-
public IDictionary<string, OpenApiLink>? Links { get; set; } = new Dictionary<string, OpenApiLink>();
61+
public IDictionary<string, IOpenApiLink>? Links { get; set; } = new Dictionary<string, IOpenApiLink>();
6262

6363
/// <summary>
6464
/// An object to hold reusable <see cref="OpenApiCallback"/> Objects.
@@ -92,7 +92,7 @@ public OpenApiComponents(OpenApiComponents? components)
9292
RequestBodies = components?.RequestBodies != null ? new Dictionary<string, OpenApiRequestBody>(components.RequestBodies) : null;
9393
Headers = components?.Headers != null ? new Dictionary<string, IOpenApiHeader>(components.Headers) : null;
9494
SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary<string, OpenApiSecurityScheme>(components.SecuritySchemes) : null;
95-
Links = components?.Links != null ? new Dictionary<string, OpenApiLink>(components.Links) : null;
95+
Links = components?.Links != null ? new Dictionary<string, IOpenApiLink>(components.Links) : null;
9696
Callbacks = components?.Callbacks != null ? new Dictionary<string, IOpenApiCallback>(components.Callbacks) : null;
9797
PathItems = components?.PathItems != null ? new Dictionary<string, OpenApiPathItem>(components.PathItems) : null;
9898
Extensions = components?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(components.Extensions) : null;

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ public bool AddComponent<T>(string id, T componentToRegister)
604604
Components.RequestBodies.Add(id, openApiRequestBody);
605605
break;
606606
case OpenApiLink openApiLink:
607-
Components.Links ??= new Dictionary<string, OpenApiLink>();
607+
Components.Links ??= new Dictionary<string, IOpenApiLink>();
608608
Components.Links.Add(id, openApiLink);
609609
break;
610610
case OpenApiCallback openApiCallback:

src/Microsoft.OpenApi/Models/OpenApiLink.cs

+31-64
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,36 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.OpenApi.Interfaces;
7+
using Microsoft.OpenApi.Models.Interfaces;
78
using Microsoft.OpenApi.Writers;
89

910
namespace Microsoft.OpenApi.Models
1011
{
1112
/// <summary>
1213
/// Link Object.
1314
/// </summary>
14-
public class OpenApiLink : IOpenApiReferenceable, IOpenApiExtensible
15+
public class OpenApiLink : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiLink
1516
{
16-
/// <summary>
17-
/// A relative or absolute reference to an OAS operation.
18-
/// This field is mutually exclusive of the operationId field, and MUST point to an Operation Object.
19-
/// </summary>
20-
public virtual string OperationRef { get; set; }
17+
/// <inheritdoc/>
18+
public string OperationRef { get; set; }
2119

22-
/// <summary>
23-
/// The name of an existing, resolvable OAS operation, as defined with a unique operationId.
24-
/// This field is mutually exclusive of the operationRef field.
25-
/// </summary>
26-
public virtual string OperationId { get; set; }
20+
/// <inheritdoc/>
21+
public string OperationId { get; set; }
2722

28-
/// <summary>
29-
/// A map representing parameters to pass to an operation as specified with operationId or identified via operationRef.
30-
/// </summary>
31-
public virtual Dictionary<string, RuntimeExpressionAnyWrapper> Parameters { get; set; } =
32-
new();
23+
/// <inheritdoc/>
24+
public IDictionary<string, RuntimeExpressionAnyWrapper> Parameters { get; set; } = new Dictionary<string, RuntimeExpressionAnyWrapper>();
3325

34-
/// <summary>
35-
/// A literal value or {expression} to use as a request body when calling the target operation.
36-
/// </summary>
37-
public virtual RuntimeExpressionAnyWrapper RequestBody { get; set; }
38-
39-
/// <summary>
40-
/// A description of the link.
41-
/// </summary>
42-
public virtual string Description { get; set; }
43-
44-
/// <summary>
45-
/// A server object to be used by the target operation.
46-
/// </summary>
47-
public virtual OpenApiServer Server { get; set; }
26+
/// <inheritdoc/>
27+
public RuntimeExpressionAnyWrapper RequestBody { get; set; }
4828

49-
/// <summary>
50-
/// This object MAY be extended with Specification Extensions.
51-
/// </summary>
52-
public virtual IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
29+
/// <inheritdoc/>
30+
public string Description { get; set; }
5331

54-
/// <summary>
55-
/// Indicates if object is populated with data or is just a reference to the data
56-
/// </summary>
57-
public virtual bool UnresolvedReference { get; set; }
32+
/// <inheritdoc/>
33+
public OpenApiServer Server { get; set; }
5834

59-
/// <summary>
60-
/// Reference pointer.
61-
/// </summary>
62-
public OpenApiReference Reference { get; set; }
35+
/// <inheritdoc/>
36+
public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
6337

6438
/// <summary>
6539
/// Parameterless constructor
@@ -69,36 +43,31 @@ public OpenApiLink() { }
6943
/// <summary>
7044
/// Initializes a copy of an <see cref="OpenApiLink"/> object
7145
/// </summary>
72-
public OpenApiLink(OpenApiLink link)
46+
public OpenApiLink(IOpenApiLink link)
7347
{
74-
OperationRef = link?.OperationRef ?? OperationRef;
75-
OperationId = link?.OperationId ?? OperationId;
76-
Parameters = link?.Parameters != null ? new(link?.Parameters) : null;
77-
RequestBody = link?.RequestBody != null ? new(link?.RequestBody) : null;
78-
Description = link?.Description ?? Description;
79-
Server = link?.Server != null ? new(link?.Server) : null;
80-
Extensions = link?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(link.Extensions) : null;
81-
UnresolvedReference = link?.UnresolvedReference ?? UnresolvedReference;
82-
Reference = link?.Reference != null ? new(link?.Reference) : null;
48+
Utils.CheckArgumentNull(link);
49+
OperationRef = link.OperationRef ?? OperationRef;
50+
OperationId = link.OperationId ?? OperationId;
51+
Parameters = link.Parameters != null ? new Dictionary<string, RuntimeExpressionAnyWrapper>(link.Parameters) : null;
52+
RequestBody = link.RequestBody != null ? new(link.RequestBody) : null;
53+
Description = link.Description ?? Description;
54+
Server = link.Server != null ? new(link.Server) : null;
55+
Extensions = link.Extensions != null ? new Dictionary<string, IOpenApiExtension>(link.Extensions) : null;
8356
}
8457

85-
/// <summary>
86-
/// Serialize <see cref="OpenApiLink"/> to Open Api v3.1
87-
/// </summary>
88-
public virtual void SerializeAsV31(IOpenApiWriter writer)
58+
/// <inheritdoc/>
59+
public void SerializeAsV31(IOpenApiWriter writer)
8960
{
9061
SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer));
9162
}
9263

93-
/// <summary>
94-
/// Serialize <see cref="OpenApiLink"/> to Open Api v3.0
95-
/// </summary>
96-
public virtual void SerializeAsV3(IOpenApiWriter writer)
64+
/// <inheritdoc/>
65+
public void SerializeAsV3(IOpenApiWriter writer)
9766
{
9867
SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer));
9968
}
10069

101-
internal virtual void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, IOpenApiSerializable> callback)
70+
internal void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, IOpenApiSerializable> callback)
10271
{
10372
Utils.CheckArgumentNull(writer);
10473

@@ -128,9 +97,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWr
12897
writer.WriteEndObject();
12998
}
13099

131-
/// <summary>
132-
/// Serialize <see cref="OpenApiLink"/> to Open Api v2.0
133-
/// </summary>
100+
/// <inheritdoc/>
134101
public void SerializeAsV2(IOpenApiWriter writer)
135102
{
136103
// Link object does not exist in V2.

src/Microsoft.OpenApi/Models/OpenApiResponse.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible
3636
/// The key of the map is a short name for the link,
3737
/// following the naming constraints of the names for Component Objects.
3838
/// </summary>
39-
public virtual IDictionary<string, OpenApiLink> Links { get; set; } = new Dictionary<string, OpenApiLink>();
39+
public virtual IDictionary<string, IOpenApiLink> Links { get; set; } = new Dictionary<string, IOpenApiLink>();
4040

4141
/// <summary>
4242
/// This object MAY be extended with Specification Extensions.
@@ -66,7 +66,7 @@ public OpenApiResponse(OpenApiResponse response)
6666
Description = response?.Description ?? Description;
6767
Headers = response?.Headers != null ? new Dictionary<string, IOpenApiHeader>(response.Headers) : null;
6868
Content = response?.Content != null ? new Dictionary<string, OpenApiMediaType>(response.Content) : null;
69-
Links = response?.Links != null ? new Dictionary<string, OpenApiLink>(response.Links) : null;
69+
Links = response?.Links != null ? new Dictionary<string, IOpenApiLink>(response.Links) : null;
7070
Extensions = response?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(response.Extensions) : null;
7171
UnresolvedReference = response?.UnresolvedReference ?? UnresolvedReference;
7272
Reference = response?.Reference != null ? new(response?.Reference) : null;

0 commit comments

Comments
 (0)