Skip to content

Commit 99e6a4a

Browse files
authored
Merge pull request #630 from microsoft/fix/port-590
fix/port 590
2 parents de62bb0 + 73ff328 commit 99e6a4a

File tree

2 files changed

+110
-12
lines changed

2 files changed

+110
-12
lines changed

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
8181
// duplicates in entity vs entityset functions/actions
8282

8383
List<string> identifiers = new();
84+
string pathHash = string.Empty;
8485
foreach (ODataSegment segment in Path.Segments)
8586
{
8687
if (segment is ODataKeySegment keySegment)
@@ -101,6 +102,18 @@ protected override void SetBasicInfo(OpenApiOperation operation)
101102
identifiers.Add(keySegment.Identifier);
102103
}
103104
}
105+
else if (segment is ODataOperationSegment opSegment)
106+
{
107+
if (opSegment.Operation is IEdmFunction function && Context.Model.IsOperationOverload(function))
108+
{
109+
// Hash the segment to avoid duplicate operationIds
110+
pathHash = string.IsNullOrEmpty(pathHash)
111+
? opSegment.GetPathHash(Context.Settings)
112+
: (pathHash + opSegment.GetPathHash(Context.Settings)).GetHashSHA256().Substring(0, 4);
113+
}
114+
115+
identifiers.Add(segment.Identifier);
116+
}
104117
else
105118
{
106119
identifiers.Add(segment.Identifier);
@@ -109,21 +122,13 @@ protected override void SetBasicInfo(OpenApiOperation operation)
109122

110123
string operationId = string.Join(".", identifiers);
111124

112-
if (EdmOperation.IsAction())
125+
if (!string.IsNullOrEmpty(pathHash))
113126
{
114-
operation.OperationId = operationId;
127+
operation.OperationId = operationId + "-" + pathHash;
115128
}
116129
else
117130
{
118-
if (Path.LastSegment is ODataOperationSegment operationSegment &&
119-
Context.Model.IsOperationOverload(operationSegment.Operation))
120-
{
121-
operation.OperationId = operationId + "-" + Path.LastSegment.GetPathHash(Context.Settings);
122-
}
123-
else
124-
{
125-
operation.OperationId = operationId;
126-
}
131+
operation.OperationId = operationId;
127132
}
128133
}
129134

test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ------------------------------------------------------------
1+
// ------------------------------------------------------------
22
// Copyright (c) Microsoft Corporation. All rights reserved.
33
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
44
// ------------------------------------------------------------
@@ -299,6 +299,99 @@ public void CreateOperationForOverloadEdmFunctionReturnsCorrectOperationId(bool
299299
}
300300
}
301301

302+
[Theory]
303+
[InlineData(true)]
304+
[InlineData(false)]
305+
public void CreateOperationForComposableOverloadEdmFunctionReturnsCorrectOperationId(bool enableOperationId)
306+
{
307+
// Arrange
308+
EdmModel model = new();
309+
EdmEntityType customer = new("NS", "Customer");
310+
customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
311+
model.AddElement(customer);
312+
313+
// Overloaded function 1
314+
EdmFunction function1 = new("NS", "MyFunction1", EdmCoreModel.Instance.GetString(false), true, null, false);
315+
function1.AddParameter("entity", new EdmEntityTypeReference(customer, false));
316+
model.AddElement(function1);
317+
318+
// Overloaded function 1
319+
EdmFunction function2 = new("NS", "MyFunction1", EdmCoreModel.Instance.GetString(false), true, null, false);
320+
function2.AddParameter("entity", new EdmEntityTypeReference(customer, false));
321+
function2.AddParameter("param", EdmCoreModel.Instance.GetString(false));
322+
323+
model.AddElement(function2);
324+
325+
// Overloaded function 2
326+
EdmFunction function3 = new("NS", "MyFunction2", EdmCoreModel.Instance.GetString(false), true, null, false);
327+
function3.AddParameter("entity2", new EdmEntityTypeReference(customer, false));
328+
model.AddElement(function3);
329+
330+
// Overloaded function 2
331+
EdmFunction function4 = new("NS", "MyFunction2", EdmCoreModel.Instance.GetString(false), true, null, false);
332+
function4.AddParameter("entity2", new EdmEntityTypeReference(customer, false));
333+
function4.AddParameter("param", EdmCoreModel.Instance.GetString(false));
334+
model.AddElement(function4);
335+
336+
EdmEntityContainer container = new("NS", "Default");
337+
EdmEntitySet customers = new(container, "Customers", customer);
338+
model.AddElement(container);
339+
340+
OpenApiConvertSettings settings = new OpenApiConvertSettings
341+
{
342+
EnableOperationId = enableOperationId,
343+
AddSingleQuotesForStringParameters = true,
344+
};
345+
ODataContext context = new(model, settings);
346+
347+
ODataPath path1 = new(new ODataNavigationSourceSegment(customers),
348+
new ODataKeySegment(customer),
349+
new ODataOperationSegment(function1),
350+
new ODataOperationSegment(function3));
351+
352+
ODataPath path2 = new(new ODataNavigationSourceSegment(customers),
353+
new ODataKeySegment(customer),
354+
new ODataOperationSegment(function1),
355+
new ODataOperationSegment(function4));
356+
357+
ODataPath path3 = new(new ODataNavigationSourceSegment(customers),
358+
new ODataKeySegment(customer),
359+
new ODataOperationSegment(function2),
360+
new ODataOperationSegment(function3));
361+
362+
ODataPath path4 = new(new ODataNavigationSourceSegment(customers),
363+
new ODataKeySegment(customer),
364+
new ODataOperationSegment(function2),
365+
new ODataOperationSegment(function4));
366+
367+
// Act
368+
var operation1 = _operationHandler.CreateOperation(context, path1);
369+
var operation2 = _operationHandler.CreateOperation(context, path2);
370+
var operation3 = _operationHandler.CreateOperation(context, path3);
371+
var operation4 = _operationHandler.CreateOperation(context, path4);
372+
373+
// Assert
374+
Assert.NotNull(operation1);
375+
Assert.NotNull(operation2);
376+
Assert.NotNull(operation3);
377+
Assert.NotNull(operation4);
378+
379+
if (enableOperationId)
380+
{
381+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-c53d", operation1.OperationId);
382+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-4d93", operation2.OperationId);
383+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-a2b2", operation3.OperationId);
384+
Assert.Equal("Customers.Customer.MyFunction1.MyFunction2-7bea", operation4.OperationId);
385+
}
386+
else
387+
{
388+
Assert.Null(operation1.OperationId);
389+
Assert.Null(operation2.OperationId);
390+
Assert.Null(operation3.OperationId);
391+
Assert.Null(operation4.OperationId);
392+
}
393+
}
394+
302395
[Theory]
303396
[InlineData(true)]
304397
[InlineData(false)]

0 commit comments

Comments
 (0)