diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs index 3bde8489..0c5a17fb 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs @@ -888,11 +888,32 @@ private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings) continue; } + ODataSegment secondLastSeg = functionPath.ElementAt(functionPath.Count - 2); + if (convertSettings.ComposableFunctionsExpansionDepth < 2 && + functionPath.LastSegment is ODataOperationSegment && + secondLastSeg is ODataOperationSegment) + { + // Only one level of composable functions expansion allowed + continue; + } + foreach (var navProperty in returnBindingEntityType.NavigationProperties()) { - ODataPath newNavigationPath = functionPath.Clone(); - newNavigationPath.Push(new ODataNavigationPropertySegment(navProperty)); - AppendPath(newNavigationPath); + /* Get number of segments already appended after the first composable function segment + */ + int composableFuncSegIndex = functionPath.Segments.IndexOf( + functionPath.Segments.FirstOrDefault( + x => x is ODataOperationSegment operationSegment && + operationSegment.Operation is IEdmFunction edmFunction && + edmFunction.IsComposable)); + int currentDepth = functionPath.Count - composableFuncSegIndex - 1; + + if (currentDepth < convertSettings.ComposableFunctionsExpansionDepth) + { + ODataPath newNavigationPath = functionPath.Clone(); + newNavigationPath.Push(new ODataNavigationPropertySegment(navProperty)); + AppendPath(newNavigationPath); + } } } } @@ -1171,6 +1192,12 @@ private void AppendBoundOperationOnOperationPath(IEdmOperation edmOperation, boo continue; } + var segName = path.LastSegment as ODataOperationSegment; + if (edmOperation.Name.Equals(segName?.Identifier)) + { + continue; + } + ODataPath newOperationPath = path.Clone(); newOperationPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model)); AppendPath(newOperationPath); diff --git a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj index cb79ac6c..bb5af0b3 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj +++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj @@ -15,13 +15,13 @@ netstandard2.0 Microsoft.OpenApi.OData true - 1.6.7 + 1.6.8 This package contains the codes you need to convert OData CSDL to Open API Document of Model. © Microsoft Corporation. All rights reserved. Microsoft OpenApi OData EDM https://github.com/Microsoft/OpenAPI.NET.OData - - Fixes empty response objects for OData type cast paths. #546 + - Adds support for configuring composable functions generations #551 Microsoft.OpenApi.OData.Reader ..\..\tool\Microsoft.OpenApi.OData.snk diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index 1e14f1f2..a6c538c8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -362,6 +362,11 @@ public bool ExpandDerivedTypesNavigationProperties /// public bool UseStringArrayForQueryOptionsSchema { get; set; } = true; + /// + /// Gets/Sets a value indicating the depth to expand composable functions. + /// + public int ComposableFunctionsExpansionDepth { get; set; } = 1; + internal OpenApiConvertSettings Clone() { var newSettings = new OpenApiConvertSettings @@ -416,7 +421,8 @@ internal OpenApiConvertSettings Clone() EnableAliasForTypeCastSegments = this.EnableAliasForTypeCastSegments, SemVerVersion = this.SemVerVersion, EnableAliasForOperationSegments = this.EnableAliasForOperationSegments, - UseStringArrayForQueryOptionsSchema = this.UseStringArrayForQueryOptionsSchema + UseStringArrayForQueryOptionsSchema = this.UseStringArrayForQueryOptionsSchema, + ComposableFunctionsExpansionDepth = this.ComposableFunctionsExpansionDepth }; return newSettings; diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt index 0b13d3ba..f94e5952 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt @@ -21,6 +21,8 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.AddEnumFlagsExtension.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.AddEnumFlagsExtension.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.AppendBoundOperationsOnDerivedTypeCastSegments.get -> bool Microsoft.OpenApi.OData.OpenApiConvertSettings.AppendBoundOperationsOnDerivedTypeCastSegments.set -> void +Microsoft.OpenApi.OData.OpenApiConvertSettings.ComposableFunctionsExpansionDepth.get -> int +Microsoft.OpenApi.OData.OpenApiConvertSettings.ComposableFunctionsExpansionDepth.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.CustomHttpMethodLinkRelMapping.get -> System.Collections.Generic.Dictionary Microsoft.OpenApi.OData.OpenApiConvertSettings.CustomHttpMethodLinkRelMapping.set -> void Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableAliasForOperationSegments.get -> bool diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs index 2c01862f..a450bc04 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs @@ -52,7 +52,7 @@ public void GetPathsForGraphBetaModelReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(16980, paths.Count()); + Assert.Equal(15210, paths.Count()); AssertGraphBetaModelPaths(paths); } @@ -117,7 +117,7 @@ public void GetPathsForGraphBetaModelWithDerivedTypesConstraintReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(17631, paths.Count()); + Assert.Equal(15861, paths.Count()); } [Theory] @@ -208,9 +208,9 @@ public void GetPathsForComposableFunctionsReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(38, paths.Count()); - Assert.Equal(20, paths.Where(p => p.LastSegment is ODataOperationSegment).Count()); - Assert.Equal(12, paths.Where(p => p.Segments.Count > 1 && p.LastSegment is ODataNavigationPropertySegment && p.Segments[p.Segments.Count - 2] is ODataOperationSegment).Count()); + Assert.Equal(26, paths.Count()); + Assert.Equal(17, paths.Where(p => p.LastSegment is ODataOperationSegment).Count()); + Assert.Equal(3, paths.Where(p => p.Segments.Count > 1 && p.LastSegment is ODataNavigationPropertySegment && p.Segments[p.Segments.Count - 2] is ODataOperationSegment).Count()); } [Fact]