Skip to content

Commit 4df4b26

Browse files
committed
chore: refactors common reference work to a base class to reduce duplication
Signed-off-by: Vincent Biret <[email protected]>
1 parent 1006879 commit 4df4b26

File tree

7 files changed

+157
-295
lines changed

7 files changed

+157
-295
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using Microsoft.OpenApi.Interfaces;
2+
using Microsoft.OpenApi.Writers;
3+
4+
namespace Microsoft.OpenApi.Models.References;
5+
/// <summary>
6+
/// Base class for OpenApiReferenceHolder.
7+
/// </summary>
8+
/// <typeparam name="T">The concrete class implementation type for the model.</typeparam>
9+
/// <typeparam name="V">The interface type for the model.</typeparam>
10+
public abstract class BaseOpenApiReferenceHolder<T, V> : IOpenApiReferenceHolder<T, V> where T : class, IOpenApiReferenceable, V
11+
{
12+
internal T _target;
13+
/// <inheritdoc/>
14+
public T Target
15+
{
16+
get
17+
{
18+
_target ??= Reference.HostDocument.ResolveReferenceTo<T>(Reference);
19+
return _target;
20+
}
21+
}
22+
/// <summary>
23+
/// Copy constructor
24+
/// </summary>
25+
/// <param name="source">The parameter reference to copy</param>
26+
protected BaseOpenApiReferenceHolder(BaseOpenApiReferenceHolder<T, V> source)
27+
{
28+
Utils.CheckArgumentNull(source);
29+
Reference = source.Reference != null ? new(source.Reference) : null;
30+
UnresolvedReference = source.UnresolvedReference;
31+
//no need to copy summary and description as if they are not overridden, they will be fetched from the target
32+
//if they are, the reference copy will handle it
33+
}
34+
private protected BaseOpenApiReferenceHolder(T target, string referenceId, ReferenceType referenceType)
35+
{
36+
_target = target;
37+
38+
Reference = new OpenApiReference()
39+
{
40+
Id = referenceId,
41+
Type = referenceType,
42+
};
43+
}
44+
/// <summary>
45+
/// Constructor initializing the reference object.
46+
/// </summary>
47+
/// <param name="referenceId">The reference Id.</param>
48+
/// <param name="hostDocument">The host OpenAPI document.</param>
49+
/// <param name="referenceType">The reference type.</param>
50+
/// <param name="externalResource">Optional: External resource in the reference.
51+
/// It may be:
52+
/// 1. a absolute/relative file path, for example: ../commons/pet.json
53+
/// 2. a Url, for example: http://localhost/pet.json
54+
/// </param>
55+
protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDocument, ReferenceType referenceType, string externalResource = null)
56+
{
57+
Utils.CheckArgumentNullOrEmpty(referenceId);
58+
59+
Reference = new OpenApiReference()
60+
{
61+
Id = referenceId,
62+
HostDocument = hostDocument,
63+
Type = referenceType,
64+
ExternalResource = externalResource
65+
};
66+
}
67+
/// <inheritdoc/>
68+
public bool UnresolvedReference { get; set; }
69+
/// <inheritdoc/>
70+
public OpenApiReference Reference { get; set; }
71+
/// <inheritdoc/>
72+
public abstract V CopyReferenceAsTargetElementWithOverrides(V source);
73+
/// <inheritdoc/>
74+
public abstract void SerializeAsV2(IOpenApiWriter writer);
75+
/// <inheritdoc/>
76+
public abstract void SerializeAsV3(IOpenApiWriter writer);
77+
/// <inheritdoc/>
78+
public abstract void SerializeAsV31(IOpenApiWriter writer);
79+
}

src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,8 @@ namespace Microsoft.OpenApi.Models.References
1313
/// <summary>
1414
/// Callback Object Reference: A reference to a map of possible out-of band callbacks related to the parent operation.
1515
/// </summary>
16-
public class OpenApiCallbackReference : IOpenApiCallback, IOpenApiReferenceHolder<OpenApiCallback, IOpenApiCallback>
16+
public class OpenApiCallbackReference : BaseOpenApiReferenceHolder<OpenApiCallback, IOpenApiCallback>, IOpenApiCallback
1717
{
18-
#nullable enable
19-
internal OpenApiCallback _target;
20-
/// <inheritdoc/>
21-
public OpenApiReference Reference { get; set; }
22-
23-
/// <inheritdoc/>
24-
public bool UnresolvedReference { get; set; }
25-
26-
/// <summary>
27-
/// Gets the target callback.
28-
/// </summary>
29-
/// <remarks>
30-
/// If the reference is not resolved, this will return null.
31-
/// </remarks>
32-
public OpenApiCallback Target
33-
#nullable restore
34-
{
35-
get
36-
{
37-
_target ??= Reference.HostDocument.ResolveReferenceTo<OpenApiCallback>(Reference);
38-
return _target;
39-
}
40-
}
41-
4218
/// <summary>
4319
/// Constructor initializing the reference object.
4420
/// </summary>
@@ -49,39 +25,20 @@ public OpenApiCallback Target
4925
/// 1. an absolute/relative file path, for example: ../commons/pet.json
5026
/// 2. a Url, for example: http://localhost/pet.json
5127
/// </param>
52-
public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null)
28+
public OpenApiCallbackReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Callback, externalResource)
5329
{
54-
Utils.CheckArgumentNullOrEmpty(referenceId);
55-
56-
Reference = new OpenApiReference()
57-
{
58-
Id = referenceId,
59-
HostDocument = hostDocument,
60-
Type = ReferenceType.Callback,
61-
ExternalResource = externalResource
62-
};
6330
}
6431

6532
/// <summary>
6633
/// Copy constructor
6734
/// </summary>
6835
/// <param name="callback">The callback reference to copy</param>
69-
public OpenApiCallbackReference(OpenApiCallbackReference callback)
36+
public OpenApiCallbackReference(OpenApiCallbackReference callback):base(callback)
7037
{
71-
Utils.CheckArgumentNull(callback);
72-
Reference = callback.Reference != null ? new(callback.Reference) : null;
73-
UnresolvedReference = callback.UnresolvedReference;
7438
}
7539

76-
internal OpenApiCallbackReference(OpenApiCallback target, string referenceId)
40+
internal OpenApiCallbackReference(OpenApiCallback target, string referenceId):base(target, referenceId, ReferenceType.Callback)
7741
{
78-
_target = target;
79-
80-
Reference = new OpenApiReference()
81-
{
82-
Id = referenceId,
83-
Type = ReferenceType.Callback,
84-
};
8542
}
8643

8744
/// <inheritdoc/>
@@ -91,7 +48,7 @@ internal OpenApiCallbackReference(OpenApiCallback target, string referenceId)
9148
public IDictionary<string, IOpenApiExtension> Extensions { get => Target?.Extensions; }
9249

9350
/// <inheritdoc/>
94-
public void SerializeAsV3(IOpenApiWriter writer)
51+
public override void SerializeAsV3(IOpenApiWriter writer)
9552
{
9653
if (!writer.GetSettings().ShouldInlineReference(Reference))
9754
{
@@ -104,7 +61,7 @@ public void SerializeAsV3(IOpenApiWriter writer)
10461
}
10562

10663
/// <inheritdoc/>
107-
public void SerializeAsV31(IOpenApiWriter writer)
64+
public override void SerializeAsV31(IOpenApiWriter writer)
10865
{
10966
if (!writer.GetSettings().ShouldInlineReference(Reference))
11067
{
@@ -117,15 +74,15 @@ public void SerializeAsV31(IOpenApiWriter writer)
11774
}
11875

11976
/// <inheritdoc/>
120-
public IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(IOpenApiCallback source)
77+
public override IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(IOpenApiCallback source)
12178
{
12279
// the copy here is never called since callbacks do not have any overridable fields.
12380
// if the spec evolves to include overridable fields for callbacks, the serialize methods will need to call this copy method.
12481
return source is OpenApiCallback ? new OpenApiCallback(this) : source;
12582
}
12683

12784
/// <inheritdoc/>
128-
public void SerializeAsV2(IOpenApiWriter writer)
85+
public override void SerializeAsV2(IOpenApiWriter writer)
12986
{
13087
// examples components are not supported in OAS 2.0
13188
Reference.SerializeAsV2(writer);

src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,8 @@ namespace Microsoft.OpenApi.Models.References
1313
/// <summary>
1414
/// Example Object Reference.
1515
/// </summary>
16-
public class OpenApiExampleReference : IOpenApiReferenceHolder<OpenApiExample, IOpenApiExample>, IOpenApiExample
16+
public class OpenApiExampleReference : BaseOpenApiReferenceHolder<OpenApiExample, IOpenApiExample>, IOpenApiExample
1717
{
18-
/// <inheritdoc/>
19-
public OpenApiReference Reference { get; set; }
20-
21-
/// <inheritdoc/>
22-
public bool UnresolvedReference { get; set; }
23-
internal OpenApiExample _target;
24-
25-
/// <summary>
26-
/// Gets the target example.
27-
/// </summary>
28-
/// <remarks>
29-
/// If the reference is not resolved, this will return null.
30-
/// </remarks>
31-
public OpenApiExample Target
32-
{
33-
get
34-
{
35-
_target ??= Reference.HostDocument.ResolveReferenceTo<OpenApiExample>(Reference);
36-
return _target;
37-
}
38-
}
39-
4018
/// <summary>
4119
/// Constructor initializing the reference object.
4220
/// </summary>
@@ -47,41 +25,20 @@ public OpenApiExample Target
4725
/// 1. a absolute/relative file path, for example: ../commons/pet.json
4826
/// 2. a Url, for example: http://localhost/pet.json
4927
/// </param>
50-
public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null)
28+
public OpenApiExampleReference(string referenceId, OpenApiDocument hostDocument, string externalResource = null):base(referenceId, hostDocument, ReferenceType.Example, externalResource)
5129
{
52-
Utils.CheckArgumentNullOrEmpty(referenceId);
53-
54-
Reference = new OpenApiReference()
55-
{
56-
Id = referenceId,
57-
HostDocument = hostDocument,
58-
Type = ReferenceType.Example,
59-
ExternalResource = externalResource
60-
};
6130
}
6231

6332
/// <summary>
6433
/// Copy constructor
6534
/// </summary>
6635
/// <param name="example">The reference to copy.</param>
67-
public OpenApiExampleReference(OpenApiExampleReference example)
36+
public OpenApiExampleReference(OpenApiExampleReference example):base(example)
6837
{
69-
Utils.CheckArgumentNull(example);
70-
Reference = example.Reference != null ? new(example.Reference) : null;
71-
UnresolvedReference = example.UnresolvedReference;
72-
//no need to copy summary and description as if they are not overridden, they will be fetched from the target
73-
//if they are, the reference copy will handle it
7438
}
7539

76-
internal OpenApiExampleReference(OpenApiExample target, string referenceId)
40+
internal OpenApiExampleReference(OpenApiExample target, string referenceId):base(target, referenceId, ReferenceType.Example)
7741
{
78-
_target = target;
79-
80-
Reference = new OpenApiReference()
81-
{
82-
Id = referenceId,
83-
Type = ReferenceType.Example,
84-
};
8542
}
8643

8744
/// <inheritdoc/>
@@ -120,7 +77,7 @@ public string Summary
12077
public JsonNode Value { get => Target?.Value; }
12178

12279
/// <inheritdoc/>
123-
public void SerializeAsV3(IOpenApiWriter writer)
80+
public override void SerializeAsV3(IOpenApiWriter writer)
12481
{
12582
if (!writer.GetSettings().ShouldInlineReference(Reference))
12683
{
@@ -133,7 +90,7 @@ public void SerializeAsV3(IOpenApiWriter writer)
13390
}
13491

13592
/// <inheritdoc/>
136-
public void SerializeAsV31(IOpenApiWriter writer)
93+
public override void SerializeAsV31(IOpenApiWriter writer)
13794
{
13895
if (!writer.GetSettings().ShouldInlineReference(Reference))
13996
{
@@ -146,13 +103,13 @@ public void SerializeAsV31(IOpenApiWriter writer)
146103
}
147104

148105
/// <inheritdoc/>
149-
public IOpenApiExample CopyReferenceAsTargetElementWithOverrides(IOpenApiExample source)
106+
public override IOpenApiExample CopyReferenceAsTargetElementWithOverrides(IOpenApiExample source)
150107
{
151108
return source is OpenApiExample ? new OpenApiExample(this) : source;
152109
}
153110

154111
/// <inheritdoc/>
155-
public void SerializeAsV2(IOpenApiWriter writer)
112+
public override void SerializeAsV2(IOpenApiWriter writer)
156113
{
157114
// examples components are not supported in OAS 2.0
158115
Reference.SerializeAsV2(writer);

0 commit comments

Comments
 (0)