Skip to content

Commit cc28ff2

Browse files
committed
fix: proxy design pattern implementation for OpenAPiExample
Signed-off-by: Vincent Biret <[email protected]>
1 parent dc8a757 commit cc28ff2

File tree

56 files changed

+462
-340
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+462
-340
lines changed

src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Linq;
67
using Microsoft.OpenApi.Exceptions;
@@ -13,7 +14,7 @@ namespace Microsoft.OpenApi.Extensions
1314
/// <summary>
1415
/// Extension methods for resolving references on <see cref="IOpenApiReferenceable"/> elements.
1516
/// </summary>
16-
public static class OpenApiReferencableExtensions
17+
public static class OpenApiReferenceableExtensions
1718
{
1819
/// <summary>
1920
/// Resolves a JSON Pointer with respect to an element, returning the referenced element.
@@ -57,13 +58,15 @@ private static IOpenApiReferenceable ResolveReferenceOnHeaderElement(
5758
string mapKey,
5859
JsonPointer pointer)
5960
{
60-
switch (propertyName)
61+
if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) &&
62+
!string.IsNullOrEmpty(mapKey) &&
63+
headerElement?.Examples != null &&
64+
headerElement.Examples.TryGetValue(mapKey, out var exampleElement) &&
65+
exampleElement is IOpenApiReferenceable referenceable)
6166
{
62-
case OpenApiConstants.Examples when mapKey != null:
63-
return headerElement.Examples[mapKey];
64-
default:
65-
throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer));
67+
return referenceable;
6668
}
69+
throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer));
6770
}
6871

6972
private static IOpenApiReferenceable ResolveReferenceOnParameterElement(
@@ -72,13 +75,15 @@ private static IOpenApiReferenceable ResolveReferenceOnParameterElement(
7275
string mapKey,
7376
JsonPointer pointer)
7477
{
75-
switch (propertyName)
78+
if (OpenApiConstants.Examples.Equals(propertyName, StringComparison.Ordinal) &&
79+
!string.IsNullOrEmpty(mapKey) &&
80+
parameterElement?.Examples != null &&
81+
parameterElement.Examples.TryGetValue(mapKey, out var exampleElement) &&
82+
exampleElement is IOpenApiReferenceable referenceable)
7683
{
77-
case OpenApiConstants.Examples when mapKey != null:
78-
return parameterElement.Examples[mapKey];
79-
default:
80-
throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer));
84+
return referenceable;
8185
}
86+
throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer));
8287
}
8388

8489
private static IOpenApiReferenceable ResolveReferenceOnResponseElement(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Collections.Generic;
2+
3+
namespace Microsoft.OpenApi.Interfaces;
4+
5+
/// <summary>
6+
/// Represents an Extensible Open API element elements can be rad from.
7+
/// </summary>
8+
public interface IOpenApiReadOnlyExtensible
9+
{
10+
/// <summary>
11+
/// Specification extensions.
12+
/// </summary>
13+
IDictionary<string, IOpenApiExtension> Extensions { get; }
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.Interfaces
7+
{
8+
/// <summary>
9+
/// A generic interface for OpenApiReferenceable objects that have a target.
10+
/// </summary>
11+
/// <typeparam name="T">Type of the target being referenced</typeparam>
12+
public interface IOpenApiReferenceHolder<out T> : IOpenApiReferenceHolder where T : IOpenApiReferenceable
13+
{
14+
/// <summary>
15+
/// Gets the resolved target object.
16+
/// </summary>
17+
T Target { get; }
18+
}
19+
/// <summary>
20+
/// A generic interface for OpenApiReferenceable objects that have a target.
21+
/// </summary>
22+
/// <typeparam name="T">The type of the target being referenced</typeparam>
23+
/// <typeparam name="V">The type of the interface implemented by both the target and the reference type</typeparam>
24+
public interface IOpenApiReferenceHolder<out T, V> : IOpenApiReferenceHolder<T> where T : IOpenApiReferenceable, V
25+
{
26+
//TODO merge this interface with the previous once all implementations are updated
27+
/// <summary>
28+
/// Copy the reference as a target element with overrides.
29+
/// </summary>
30+
V CopyReferenceAsTargetElementWithOverrides(V source);
31+
}
32+
/// <summary>
33+
/// A generic interface for OpenApiReferenceable objects that have a target.
34+
/// </summary>
35+
public interface IOpenApiReferenceHolder : IOpenApiSerializable
36+
{
37+
/// <summary>
38+
/// Indicates if object is populated with data or is just a reference to the data
39+
/// </summary>
40+
bool UnresolvedReference { get; set; }
41+
42+
/// <summary>
43+
/// Reference object.
44+
/// </summary>
45+
OpenApiReference Reference { get; set; }
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
using Microsoft.OpenApi.Models;
5-
64
namespace Microsoft.OpenApi.Interfaces
75
{
86
/// <summary>
97
/// Represents an Open API element is referenceable.
108
/// </summary>
119
public interface IOpenApiReferenceable : IOpenApiSerializable
1210
{
13-
/// <summary>
14-
/// Indicates if object is populated with data or is just a reference to the data
15-
/// </summary>
16-
bool UnresolvedReference { get; set; }
17-
18-
/// <summary>
19-
/// Reference object.
20-
/// </summary>
21-
OpenApiReference Reference { get; set; }
2211
}
2312
}

src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceableWithTarget.cs

-17
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.OpenApi.Interfaces;
2+
3+
namespace Microsoft.OpenApi.Models.Interfaces;
4+
5+
/// <summary>
6+
/// Describes an element that has a summary and description.
7+
/// </summary>
8+
public interface IOpenApiDescribedElement : IOpenApiElement
9+
{
10+
/// <summary>
11+
/// Short description for the example.
12+
/// </summary>
13+
public string Summary { get; set; }
14+
15+
/// <summary>
16+
/// Long description for the example.
17+
/// CommonMark syntax MAY be used for rich text representation.
18+
/// </summary>
19+
public string Description { get; set; }
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Text.Json.Nodes;
2+
using Microsoft.OpenApi.Interfaces;
3+
4+
namespace Microsoft.OpenApi.Models.Interfaces;
5+
6+
/// <summary>
7+
/// Defines the base properties for the example 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 IOpenApiExample : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible
11+
{
12+
/// <summary>
13+
/// Embedded literal example. The value field and externalValue field are mutually
14+
/// exclusive. To represent examples of media types that cannot naturally represented
15+
/// in JSON or YAML, use a string value to contain the example, escaping where necessary.
16+
/// </summary>
17+
public JsonNode Value { get; }
18+
19+
/// <summary>
20+
/// A URL that points to the literal example.
21+
/// This provides the capability to reference examples that cannot easily be
22+
/// included in JSON or YAML documents.
23+
/// The value field and externalValue field are mutually exclusive.
24+
/// </summary>
25+
public string ExternalValue { get; }
26+
}

src/Microsoft.OpenApi/Models/OpenApiComponents.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.OpenApi.Interfaces;
7+
using Microsoft.OpenApi.Models.Interfaces;
78
using Microsoft.OpenApi.Models.References;
89
using Microsoft.OpenApi.Writers;
910

@@ -35,7 +36,7 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible
3536
/// <summary>
3637
/// An object to hold reusable <see cref="OpenApiExample"/> Objects.
3738
/// </summary>
38-
public virtual IDictionary<string, OpenApiExample>? Examples { get; set; } = new Dictionary<string, OpenApiExample>();
39+
public virtual IDictionary<string, IOpenApiExample>? Examples { get; set; } = new Dictionary<string, IOpenApiExample>();
3940

4041
/// <summary>
4142
/// An object to hold reusable <see cref="OpenApiRequestBody"/> Objects.
@@ -87,7 +88,7 @@ public OpenApiComponents(OpenApiComponents? components)
8788
Schemas = components?.Schemas != null ? new Dictionary<string, OpenApiSchema>(components.Schemas) : null;
8889
Responses = components?.Responses != null ? new Dictionary<string, OpenApiResponse>(components.Responses) : null;
8990
Parameters = components?.Parameters != null ? new Dictionary<string, OpenApiParameter>(components.Parameters) : null;
90-
Examples = components?.Examples != null ? new Dictionary<string, OpenApiExample>(components.Examples) : null;
91+
Examples = components?.Examples != null ? new Dictionary<string, IOpenApiExample>(components.Examples) : null;
9192
RequestBodies = components?.RequestBodies != null ? new Dictionary<string, OpenApiRequestBody>(components.RequestBodies) : null;
9293
Headers = components?.Headers != null ? new Dictionary<string, OpenApiHeader>(components.Headers) : null;
9394
SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary<string, OpenApiSecurityScheme>(components.SecuritySchemes) : null;
@@ -160,7 +161,7 @@ public void SerializeAsV3(IOpenApiWriter writer)
160161
/// Serialize <see cref="OpenApiComponents"/>.
161162
/// </summary>
162163
private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
163-
Action<IOpenApiWriter, IOpenApiSerializable> callback, Action<IOpenApiWriter, IOpenApiReferenceable> action)
164+
Action<IOpenApiWriter, IOpenApiSerializable> callback, Action<IOpenApiWriter, IOpenApiReferenceHolder> action)
164165
{
165166
// Serialize each referenceable object as full object without reference if the reference in the object points to itself.
166167
// If the reference exists but points to other objects, the object is serialized to just that reference.

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Threading.Tasks;
1212
using Microsoft.OpenApi.Extensions;
1313
using Microsoft.OpenApi.Interfaces;
14+
using Microsoft.OpenApi.Models.Interfaces;
1415
using Microsoft.OpenApi.Models.References;
1516
using Microsoft.OpenApi.Reader;
1617
using Microsoft.OpenApi.Services;
@@ -615,7 +616,7 @@ public bool AddComponent<T>(string id, T componentToRegister)
615616
Components.PathItems.Add(id, openApiPathItem);
616617
break;
617618
case OpenApiExample openApiExample:
618-
Components.Examples ??= new Dictionary<string, OpenApiExample>();
619+
Components.Examples ??= new Dictionary<string, IOpenApiExample>();
619620
Components.Examples.Add(id, openApiExample);
620621
break;
621622
case OpenApiHeader openApiHeader:
@@ -645,9 +646,10 @@ public static void ResolveSchemas(OpenApiComponents? components, Dictionary<stri
645646
walker.Walk(components);
646647
}
647648

648-
public override void Visit(IOpenApiReferenceable referenceable)
649+
/// <inheritdoc/>
650+
public override void Visit(IOpenApiReferenceHolder referenceHolder)
649651
{
650-
switch (referenceable)
652+
switch (referenceHolder)
651653
{
652654
case OpenApiSchema schema:
653655
if (!Schemas.ContainsKey(schema.Reference.Id))
@@ -659,7 +661,7 @@ public override void Visit(IOpenApiReferenceable referenceable)
659661
default:
660662
break;
661663
}
662-
base.Visit(referenceable);
664+
base.Visit(referenceHolder);
663665
}
664666

665667
public override void Visit(OpenApiSchema schema)

0 commit comments

Comments
 (0)