Skip to content

Commit 9b0ba05

Browse files
authored
Adds support for retrieving collection of enum values from UpdateMethod property of UpdateRestrictions annotation (#567)
* Add method for retrieving collection of enum values * Update the UpdateMethod to an IList * Add support for generating both PUT and PATCH operations * Update unit tests to validate support for both PUT and PATCH * Update release note * Small typo fix * Another very small typo fix * Update function to account for flagged enums * Use flags attribute on enum type; revert property name
1 parent e6efed8 commit 9b0ba05

File tree

7 files changed

+73
-36
lines changed

7 files changed

+73
-36
lines changed

src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,30 @@ public static string GetString(this IEdmRecordExpression record, string property
9494
/// <param name="propertyName">The property name.</param>
9595
/// <returns>The Enum value or null.</returns>
9696
public static T? GetEnum<T>(this IEdmRecordExpression record, string propertyName)
97-
where T : struct
97+
where T : struct, Enum
9898
{
9999
Utils.CheckArgumentNull(record, nameof(record));
100100
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
101101

102-
return (record.Properties?.FirstOrDefault(e => propertyName.Equals(e.Name, StringComparison.Ordinal)) is IEdmPropertyConstructor property &&
102+
if (record.Properties?.FirstOrDefault(e => propertyName.Equals(e.Name, StringComparison.Ordinal))
103+
is IEdmPropertyConstructor property &&
103104
property.Value is IEdmEnumMemberExpression value &&
104105
value.EnumMembers != null &&
105-
value.EnumMembers.Any() &&
106-
Enum.TryParse(value.EnumMembers.First().Name, out T result)) ?
107-
result :
108-
null;
106+
value.EnumMembers.Any())
107+
{
108+
long combinedValue = 0;
109+
foreach (var enumMember in value.EnumMembers)
110+
{
111+
if (Enum.TryParse(enumMember.Name, out T enumValue))
112+
{
113+
combinedValue |= Convert.ToInt64(enumValue);
114+
}
115+
}
116+
117+
return (T)Enum.ToObject(typeof(T), combinedValue);
118+
}
119+
120+
return null;
109121
}
110122

111123
/// <summary>

src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
<TargetFrameworks>net8.0</TargetFrameworks>
1616
<PackageId>Microsoft.OpenApi.OData</PackageId>
1717
<SignAssembly>true</SignAssembly>
18-
<Version>2.0.0-preview.1</Version>
18+
<Version>2.0.0-preview.2</Version>
1919
<Description>This package contains the codes you need to convert OData CSDL to Open API Document of Model.</Description>
2020
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
2121
<PackageTags>Microsoft OpenApi OData EDM</PackageTags>
2222
<RepositoryUrl>https://github.com/Microsoft/OpenAPI.NET.OData</RepositoryUrl>
2323
<PackageReleaseNotes>
2424
- Upgraded to Microsoft.Odata.Edm 8.0.0
25-
- Cleaned up obsolete APIs
26-
- Changed target framework to net8.0
25+
- Cleaned up obsolete APIs
26+
- Changed target framework to net8.0
27+
- Adds support for retrieving collection of enum values from UpdateMethod property of UpdateRestrictions annotation #564
2728
</PackageReleaseNotes>
2829
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
2930
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ public void AddUpdateOperation(OpenApiPathItem item)
7070
if ((Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths && isUpdatable) ||
7171
!Context.Settings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths)
7272
{
73-
if (updateRestrictions != null && updateRestrictions.IsUpdateMethodPut)
73+
if (updateRestrictions?.IsUpdateMethodPutAndPatch == true)
74+
{
75+
AddOperation(item, OperationType.Put);
76+
AddOperation(item, OperationType.Patch);
77+
}
78+
else if (updateRestrictions?.IsUpdateMethodPut == true)
7479
{
7580
AddOperation(item, OperationType.Put);
7681
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ protected override void SetOperations(OpenApiPathItem item)
4040
updateRestrictions ??= entityUpdateRestrictions;
4141
if (updateRestrictions?.IsUpdatable ?? true)
4242
{
43-
if (updateRestrictions != null && updateRestrictions.IsUpdateMethodPut)
43+
if (updateRestrictions?.IsUpdateMethodPutAndPatch == true)
44+
{
45+
AddOperation(item, OperationType.Put);
46+
AddOperation(item, OperationType.Patch);
47+
}
48+
else if (updateRestrictions?.IsUpdateMethodPut == true)
4449
{
4550
AddOperation(item, OperationType.Put);
4651
}

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,23 @@ private void AddDeleteOperation(OpenApiPathItem item, NavigationPropertyRestrict
243243

244244
private void AddUpdateOperation(OpenApiPathItem item, UpdateRestrictionsType updateRestrictionsType)
245245
{
246-
if (updateRestrictionsType == null || updateRestrictionsType.IsUpdatable)
247-
{
248-
if (updateRestrictionsType != null && updateRestrictionsType.IsUpdateMethodPut)
249-
{
250-
AddOperation(item, OperationType.Put);
251-
}
252-
else
253-
{
254-
AddOperation(item, OperationType.Patch);
255-
}
256-
}
246+
if (updateRestrictionsType?.IsUpdatable ?? true)
247+
{
248+
if (updateRestrictionsType?.IsUpdateMethodPutAndPatch == true)
249+
{
250+
AddOperation(item, OperationType.Put);
251+
AddOperation(item, OperationType.Patch);
252+
}
253+
else if (updateRestrictionsType?.IsUpdateMethodPut == true)
254+
{
255+
AddOperation(item, OperationType.Put);
256+
}
257+
else
258+
{
259+
AddOperation(item, OperationType.Patch);
260+
}
261+
}
262+
257263
}
258264

259265
/// <inheritdoc/>

src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/UpdateRestrictionsType.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
44
// ------------------------------------------------------------
55

6+
using System;
67
using System.Collections.Generic;
78
using System.Linq;
89
using Microsoft.OData.Edm.Vocabularies;
@@ -14,17 +15,18 @@ namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities
1415
/// <summary>
1516
/// Enumerates HTTP methods that can be used to update entities
1617
/// </summary>
18+
[Flags]
1719
internal enum HttpMethod
1820
{
1921
/// <summary>
2022
/// The HTTP PATCH Method
2123
/// </summary>
22-
PATCH,
24+
PATCH = 1,
2325

2426
/// <summary>
2527
/// The HTTP PUT Method
2628
/// </summary>
27-
PUT
29+
PUT = 2
2830
}
2931
/// <summary>
3032
/// Complex Type: Org.OData.Capabilities.V1.UpdateRestrictionsType
@@ -46,10 +48,10 @@ internal class UpdateRestrictionsType : IRecord
4648
/// <summary>
4749
/// Gets the value indicating Entities can be inserted, updated, and deleted via a PATCH request with a delta payload.
4850
/// </summary>
49-
public bool? DeltaUpdateSupported { get; private set; }
50-
51+
public bool? DeltaUpdateSupported { get; private set; }
52+
5153
/// <summary>
52-
/// Gets the value indicating the HTTP Method (PUT or PATCH) for updating an entity.
54+
/// Gets the values indicating the HTTP Method (PUT and/or PATCH) for updating an entity.
5355
/// If null, PATCH should be supported and PUT MAY be supported.
5456
/// </summary>
5557
public HttpMethod? UpdateMethod { get; private set; }
@@ -124,10 +126,16 @@ public bool IsNonUpdatableNavigationProperty(string navigationPropertyPath)
124126
}
125127

126128
/// <summary>
127-
/// Tests whether the update method for the entity has been explicitly specified as PUT
129+
/// Tests whether the update method for the target has been explicitly specified as PUT
128130
/// </summary>
129131
public bool IsUpdateMethodPut => UpdateMethod.HasValue && UpdateMethod.Value == HttpMethod.PUT;
130132

133+
/// <summary>
134+
/// Tests whether the update method for the target has been explicitly specified as PATCH and PUT
135+
/// </summary>
136+
public bool IsUpdateMethodPutAndPatch => UpdateMethod.HasValue &&
137+
(UpdateMethod.Value & (HttpMethod.PUT | HttpMethod.PATCH)) == (HttpMethod.PUT | HttpMethod.PATCH);
138+
131139
/// <summary>
132140
/// Lists the media types acceptable for the request content
133141
/// </summary>
@@ -157,7 +165,7 @@ public void Initialize(IEdmRecordExpression record)
157165
// DeltaUpdateSupported
158166
DeltaUpdateSupported = record.GetBoolean("DeltaUpdateSupported");
159167

160-
// UpdateMethod
168+
// UpdateMethod
161169
UpdateMethod = record.GetEnum<HttpMethod>("UpdateMethod");
162170

163171
// FilterSegmentSupported

test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/NavigationPropertyPathItemHandlerTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ public void CreatePathItemForNavigationPropertyAndUpdateMethodUpdateRestrictions
452452
<PropertyValue Property=""UpdateRestrictions"" >
453453
<Record>
454454
<PropertyValue Property=""UpdateMethod"">
455-
<EnumMember>Org.OData.Capabilities.V1.HttpMethod/PUT</EnumMember>
455+
<EnumMember>Org.OData.Capabilities.V1.HttpMethod/PUT Org.OData.Capabilities.V1.HttpMethod/PATCH </EnumMember>
456456
</PropertyValue>
457457
<PropertyValue Property=""Updatable"" Bool=""{1}"" />
458458
</Record>
@@ -488,21 +488,21 @@ public void CreatePathItemForNavigationPropertyAndUpdateMethodUpdateRestrictions
488488
if (isContainment)
489489
{
490490
expected = updatable
491-
? (new[] { OperationType.Get, OperationType.Put, OperationType.Delete })
492-
: (new[] { OperationType.Get, OperationType.Delete });
491+
? ([OperationType.Get, OperationType.Put, OperationType.Patch, OperationType.Delete])
492+
: ([OperationType.Get, OperationType.Delete]);
493493
}
494494
else
495495
{
496496
expected = updatable
497-
? (new[] { OperationType.Get, OperationType.Put })
498-
: (new[] { OperationType.Get });
497+
? ([OperationType.Get, OperationType.Put, OperationType.Patch,])
498+
: ([OperationType.Get]);
499499
}
500500
}
501501
else
502502
{
503503
expected = isContainment
504-
? (new[] { OperationType.Get, OperationType.Patch, OperationType.Delete })
505-
: (new[] { OperationType.Get });
504+
? ([OperationType.Get, OperationType.Patch, OperationType.Delete])
505+
: ([OperationType.Get]);
506506

507507
}
508508

0 commit comments

Comments
 (0)