Skip to content

Commit 34d13b2

Browse files
authored
Merge pull request #173 from microsoft/feature/dm/add-path-parameters-to-path-item
Add support for declaring path parameters on path item object instead of operation object
2 parents dcdba31 + b171a2d commit 34d13b2

13 files changed

+193
-46
lines changed

src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,56 @@ public static IList<OpenApiParameter> CreateKeyParameters(this ODataContext cont
216216
return parameters;
217217
}
218218

219+
/// <summary>
220+
/// Creates the path parameters for the <see cref="ODataPath"/>
221+
/// </summary>
222+
/// <param name="path">The ODataPath</param>
223+
/// <param name="context">The OData context.</param>
224+
/// <returns>The created list of <see cref="OpenApiParameter"/></returns>
225+
public static List<OpenApiParameter> CreatePathParameters(this ODataPath path, ODataContext context)
226+
{
227+
List<OpenApiParameter> pathParameters = new();
228+
var parameterMappings = path.CalculateParameterMapping(context.Settings);
229+
230+
foreach (ODataKeySegment keySegment in path.OfType<ODataKeySegment>())
231+
{
232+
IDictionary<string, string> mapping = parameterMappings[keySegment];
233+
pathParameters.AddRange(context.CreateKeyParameters(keySegment, mapping));
234+
}
235+
236+
// Add the route prefix parameter v1{data}
237+
if (context.Settings.RoutePathPrefixProvider?.Parameters != null)
238+
{
239+
pathParameters.AddRange(context.Settings.RoutePathPrefixProvider.Parameters);
240+
}
241+
242+
return pathParameters;
243+
}
244+
245+
/// <summary>
246+
/// Adds an OpenApiParameter to an existing list of OpenApiParameters.
247+
/// If a parameter with the same name already exists in the list, the new parameter name
248+
/// if suffixed with an incrementing number
249+
/// </summary>
250+
/// <param name="parameters">The list of OpenApiParameters to be appended to</param>
251+
/// <param name="parameter">The new OpenApiParameter to be appended</param>
252+
public static void AppendParameter(this IList<OpenApiParameter> parameters, OpenApiParameter parameter)
253+
{
254+
HashSet<string> parametersSet = new(parameters.Select(p => p.Name));
255+
256+
string parameterName = parameter.Name;
257+
int index = 1;
258+
while (parametersSet.Contains(parameterName))
259+
{
260+
parameterName += index.ToString();
261+
index++;
262+
}
263+
264+
parameter.Name = parameterName;
265+
parametersSet.Add(parameterName);
266+
parameters.Add(parameter);
267+
}
268+
219269
/// <summary>
220270
/// Create the $top parameter.
221271
/// </summary>

src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ public string PathPrefix
225225
/// </summary>
226226
public string InnerErrorComplexTypeName { get; set; } = "InnerError";
227227

228+
/// <summary>
229+
/// Gets/Sets a value indicating whether path parameters should be declared on path item object.
230+
/// If true, path parameters will be declared on the path item object, otherwise they
231+
/// will be declared on the operation object.
232+
/// </summary>
233+
public bool DeclarePathParametersOnPathItem { get; set; } = false;
234+
228235
/// <summary>
229236
/// Gets/Sets a value indicating whether or not to use restrictions annotations to generate paths for complex properties.
230237
/// </summary>

src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected override void SetParameters(OpenApiOperation operation)
3030
{
3131
foreach (var param in Context.CreateParameters(functionImport.Function, OperationImportSegment.ParameterMappings))
3232
{
33-
AppendParameter(operation, param);
33+
operation.Parameters.AppendParameter(param);
3434
}
3535
}
3636
else
@@ -39,7 +39,7 @@ protected override void SetParameters(OpenApiOperation operation)
3939
// and it contains specific Parameter Objects for the allowed system query options.
4040
foreach (var param in Context.CreateParameters(functionImport))
4141
{
42-
AppendParameter(operation, param);
42+
operation.Parameters.AppendParameter(param);
4343
}
4444
}
4545
}

src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ protected override void SetParameters(OpenApiOperation operation)
138138
IList<OpenApiParameter> parameters = Context.CreateParameters(function, OperationSegment.ParameterMappings);
139139
foreach (var parameter in parameters)
140140
{
141-
AppendParameter(operation, parameter);
141+
operation.Parameters.AppendParameter(parameter);
142142
}
143143
}
144144
else
@@ -153,7 +153,7 @@ protected override void SetParameters(OpenApiOperation operation)
153153
{
154154
foreach (var parameter in parameters)
155155
{
156-
AppendParameter(operation, parameter);
156+
operation.Parameters.AppendParameter(parameter);
157157
}
158158
}
159159
}

src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ protected override void SetResponses(OpenApiOperation operation)
8989
if (Context.Settings.ShowLinks)
9090
{
9191
links = Context.CreateLinks(entityType: EntitySet.EntityType(), entityName: EntitySet.Name,
92-
entityKind: EntitySet.ContainerElementKind.ToString(), parameters: operation.Parameters);
92+
entityKind: EntitySet.ContainerElementKind.ToString(), PathParameters);
9393
}
9494

9595
if (schema == null)

src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ protected override void SetResponses(OpenApiOperation operation)
118118
string operationId = GetOperationId();
119119

120120
links = Context.CreateLinks(entityType: NavigationProperty.ToEntityType(), entityName: NavigationProperty.Name,
121-
entityKind: NavigationProperty.PropertyKind.ToString(), parameters: operation.Parameters,
121+
entityKind: NavigationProperty.PropertyKind.ToString(), parameters: PathParameters,
122122
navPropOperationId: operationId);
123123
}
124124

src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs

Lines changed: 10 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ internal abstract class OperationHandler : IOperationHandler
2525

2626
protected IDictionary<ODataSegment, IDictionary<string, string>> ParameterMappings;
2727

28+
/// <summary>
29+
/// The path parameters in the path
30+
/// </summary>
31+
protected IList<OpenApiParameter> PathParameters;
32+
2833
/// <inheritdoc/>
2934
public virtual OpenApiOperation CreateOperation(ODataContext context, ODataPath path)
3035
{
@@ -139,25 +144,16 @@ protected virtual void SetRequestBody(OpenApiOperation operation)
139144
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
140145
protected virtual void SetParameters(OpenApiOperation operation)
141146
{
142-
foreach (ODataKeySegment keySegment in Path.OfType<ODataKeySegment>())
147+
PathParameters = Path.CreatePathParameters(Context);
148+
if (!Context.Settings.DeclarePathParametersOnPathItem)
143149
{
144-
IDictionary<string, string> mapping = ParameterMappings[keySegment];
145-
foreach (var p in Context.CreateKeyParameters(keySegment, mapping))
150+
foreach (var parameter in PathParameters)
146151
{
147-
AppendParameter(operation, p);
152+
operation.Parameters.AppendParameter(parameter);
148153
}
149154
}
150155

151156
AppendCustomParameters(operation);
152-
153-
// Add the route prefix parameter v1{data}
154-
if (Context.Settings.RoutePathPrefixProvider != null && Context.Settings.RoutePathPrefixProvider.Parameters != null)
155-
{
156-
foreach (var parameter in Context.Settings.RoutePathPrefixProvider.Parameters)
157-
{
158-
operation.Parameters.Add(parameter);
159-
}
160-
}
161157
}
162158

163159
/// <summary>
@@ -247,32 +243,8 @@ protected static void AppendCustomParameters(OpenApiOperation operation, IList<C
247243
}
248244
}
249245

250-
AppendParameter(operation, parameter);
251-
}
252-
}
253-
254-
protected static void AppendParameter(OpenApiOperation operation, OpenApiParameter parameter)
255-
{
256-
HashSet<string> set = new HashSet<string>(operation.Parameters.Select(p => p.Name));
257-
258-
if (!set.Contains(parameter.Name))
259-
{
260-
operation.Parameters.Add(parameter);
261-
return;
246+
operation.Parameters.AppendParameter(parameter);
262247
}
263-
264-
int index = 1;
265-
string originalName = parameter.Name;
266-
string newName;
267-
do
268-
{
269-
newName = originalName + index.ToString();
270-
index++;
271-
}
272-
while (set.Contains(newName));
273-
274-
parameter.Name = newName;
275-
operation.Parameters.Add(parameter);
276248
}
277249
}
278250
}

src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ protected override void SetResponses(OpenApiOperation operation)
9999
string operationId = GetOperationId();
100100

101101
links = Context.CreateLinks(entityType: NavigationProperty.ToEntityType(), entityName: NavigationProperty.Name,
102-
entityKind: NavigationProperty.PropertyKind.ToString(), parameters: operation.Parameters,
102+
entityKind: NavigationProperty.PropertyKind.ToString(), parameters: PathParameters,
103103
navPropOperationId: operationId);
104104
}
105105

src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected override void SetResponses(OpenApiOperation operation)
8787
if (Context.Settings.ShowLinks)
8888
{
8989
links = Context.CreateLinks(entityType: Singleton.EntityType(), entityName: Singleton.Name,
90-
entityKind: Singleton.ContainerElementKind.ToString(), parameters: operation.Parameters);
90+
entityKind: Singleton.ContainerElementKind.ToString(), parameters: PathParameters);
9191
}
9292

9393
if (schema == null)

src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.OpenApi.Models;
88
using Microsoft.OpenApi.OData.Common;
99
using Microsoft.OpenApi.OData.Edm;
10+
using Microsoft.OpenApi.OData.Generator;
1011
using Microsoft.OpenApi.OData.Operation;
1112
using Microsoft.OpenApi.OData.Properties;
1213

@@ -45,6 +46,11 @@ public virtual OpenApiPathItem CreatePathItem(ODataContext context, ODataPath pa
4546

4647
SetBasicInfo(item);
4748

49+
if (Context.Settings.DeclarePathParametersOnPathItem)
50+
{
51+
SetParameters(item);
52+
}
53+
4854
SetOperations(item);
4955

5056
SetExtensions(item);
@@ -101,5 +107,17 @@ protected virtual void AddOperation(OpenApiPathItem item, OperationType operatio
101107
IOperationHandler operationHander = provider.GetHandler(Path.Kind, operationType);
102108
item.AddOperation(operationType, operationHander.CreateOperation(Context, Path));
103109
}
110+
111+
/// <summary>
112+
/// Set the parameters information for <see cref="OpenApiPathItem"/>
113+
/// </summary>
114+
/// <param name="item">The <see cref="OpenApiPathItem"/>.</param>
115+
protected virtual void SetParameters(OpenApiPathItem item)
116+
{
117+
foreach (var parameter in Path.CreatePathParameters(Context))
118+
{
119+
item.Parameters.AppendParameter(parameter);
120+
}
121+
}
104122
}
105123
}

0 commit comments

Comments
 (0)