Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Resolves operation ids for $count and overloaded functions paths #386

Merged
merged 9 commits into from
May 25, 2023
21 changes: 11 additions & 10 deletions src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,9 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
/// Generates the operation id prefix from an OData type cast path.
/// </summary>
/// <param name="path">The target <see cref="ODataPath"/>.</param>
/// <param name="includeListOrGetPrefix">Optional: Whether to include the List or Get prefix to the generated operation id.</param>
/// <returns>The operation id prefix generated from the OData type cast path.</returns>
internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path)
internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path, bool includeListOrGetPrefix = true)
{
// Get the segment before the last OData type cast segment
ODataTypeCastSegment typeCastSegment = path.Segments.OfType<ODataTypeCastSegment>()?.Last();
Expand Down Expand Up @@ -309,24 +310,24 @@ internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path
string operationId = null;
if (secondLastSegment is ODataComplexPropertySegment complexSegment)
{
string listOrGet = complexSegment.Property.Type.IsCollection() ? "List" : "Get";
string listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less work when we enable NRT this way

Suggested change
string listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
string listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : string.Empty;

operationId = GenerateComplexPropertyPathOperationId(path, listOrGet);
}
else if (secondLastSegment as ODataNavigationPropertySegment is not null || isIndexedCollValuedNavProp)
{
string prefix = "Get";
if (!isIndexedCollValuedNavProp &&
(secondLastSegment as ODataNavigationPropertySegment)?.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
string listOrGet = null;
if (includeListOrGetPrefix)
{
prefix = "List";
listOrGet = !isIndexedCollValuedNavProp && (secondLastSegment as ODataNavigationPropertySegment)?.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many ? "List" : "Get";
}

operationId = GenerateNavigationPropertyPathOperationId(path, prefix);
operationId = GenerateNavigationPropertyPathOperationId(path, listOrGet);
}
else if (secondLastSegment is ODataKeySegment keySegment && !isIndexedCollValuedNavProp)
{
string entityTypeName = keySegment.EntityType.Name;
string operationName = $"Get{Utils.UpperFirstChar(entityTypeName)}";
string getPrefix = includeListOrGetPrefix ? "Get" : null;
string operationName = $"{getPrefix}{Utils.UpperFirstChar(entityTypeName)}";
if (keySegment.IsAlternateKey)
{
string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
Expand All @@ -338,8 +339,8 @@ internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path
else if (secondLastSegment is ODataNavigationSourceSegment)
{
operationId = (entitySet != null)
? entitySet.Name + "." + entitySet.EntityType().Name + ".List" + Utils.UpperFirstChar(entitySet.EntityType().Name)
: singleton.Name + "." + singleton.EntityType().Name + ".Get" + Utils.UpperFirstChar(singleton.EntityType().Name);
? entitySet.Name + "." + entitySet.EntityType().Name + $".{(includeListOrGetPrefix ? "List" : null)}" + Utils.UpperFirstChar(entitySet.EntityType().Name)
: singleton.Name + "." + singleton.EntityType().Name + $".{(includeListOrGetPrefix ? "Get" : null)}" + Utils.UpperFirstChar(singleton.EntityType().Name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Singleton can technically be null here

}

return operationId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public static bool IsOperationOverload(this IEdmModel model, IEdmOperation opera

return model.GetAllElements().OfType<IEdmOperation>()
.Where(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
o.Parameters.First().Type.Definition == operation.Parameters.First().Type.Definition
o.Parameters.First().Type.Definition.FullTypeName() == operation.Parameters.First().Type.Definition.FullTypeName()
).Count() > 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,13 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<PackageId>Microsoft.OpenApi.OData</PackageId>
<SignAssembly>true</SignAssembly>
<Version>1.4.0</Version>
<Version>1.5.0-preview1</Version>
<Description>This package contains the codes you need to convert OData CSDL to Open API Document of Model.</Description>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageTags>Microsoft OpenApi OData EDM</PackageTags>
<RepositoryUrl>https://github.com/Microsoft/OpenAPI.NET.OData</RepositoryUrl>
<PackageReleaseNotes>
- DELETE methods should always return response status code #204
- Aliases or strips namespace prefixes from segment names when and where applicable #365
- Adds support for all Org.OData.Core.V1.RevisionKind enum values #372
- Use directly annotated CountRestriction annotations when creating $count segments for collection-valued navigation properties #328
- Use MediaType annotation to set the content types of operations with Edm.Stream return types #342
- Retrieves navigation properties from base types #371
- Adds support for RequiresExplicitBinding and ExplicitOperationBindings annotations for operations #323 #232
- Resolves operation ids for $count and overloaded functions paths #382, #383
</PackageReleaseNotes>
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
else if (SecondLastSegment is ODataTypeCastSegment odataTypeCastSegment)
{
IEdmNamedElement targetStructuredType = odataTypeCastSegment.StructuredType as IEdmNamedElement;
operation.OperationId = $"{EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path)}.GetCount.As{Utils.UpperFirstChar(targetStructuredType.Name)}-{Path.GetPathHash(Context.Settings)}";
operation.OperationId = $"{EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path, false)}.GetCount.As{Utils.UpperFirstChar(targetStructuredType.Name)}-{Path.GetPathHash(Context.Settings)}";
}
else if (SecondLastSegment is ODataComplexPropertySegment)
{
Expand Down
Loading