- adds support for entity set down cast
Signed-off-by: Vincent Biret <vibiret@microsoft.com>
This commit is contained in:
parent
4ee8e9e5eb
commit
d0b3e2079f
|
@ -190,6 +190,15 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
if(count?.Countable ?? true)
|
||||
CreateCountPath(path, convertSettings);
|
||||
|
||||
//TODO read the cast restrictions annotation
|
||||
var derivedTypes = _model
|
||||
.FindAllDerivedTypes(entitySet.EntityType())
|
||||
.Where(x => x.TypeKind == EdmTypeKind.Entity)
|
||||
.OfType<IEdmEntityType>()
|
||||
.ToArray();
|
||||
if(derivedTypes.Any())
|
||||
CreateTypeCastPaths(path, convertSettings, derivedTypes);
|
||||
|
||||
path.Push(new ODataKeySegment(entityType));
|
||||
AppendPath(path.Clone());
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
@ -31,6 +32,7 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
|||
internal ODataSegment LastSecondSegment { get; set; }
|
||||
|
||||
private NavigationPropertyRestriction restriction;
|
||||
private IEdmEntitySet entitySet;
|
||||
private IEdmNavigationProperty navigationProperty;
|
||||
private IEdmEntityType parentEntityType;
|
||||
private IEdmEntityType targetEntityType;
|
||||
|
@ -67,9 +69,17 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(LastSecondSegment is ODataNavigationSourceSegment sourceSegment && sourceSegment.NavigationSource is IEdmEntitySet eSet)
|
||||
{
|
||||
entitySet = eSet;
|
||||
NavigationRestrictionsType navigation = Context.Model.GetRecord<NavigationRestrictionsType>(eSet, CapabilitiesConstants.NavigationRestrictions);
|
||||
if (navigation?.RestrictedProperties != null)
|
||||
{
|
||||
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty == null);
|
||||
}
|
||||
}
|
||||
//TODO previous segment is a key
|
||||
//TODO previous segment is a single nav property
|
||||
//TODO previous segment is an entity set
|
||||
if(path.Last() is ODataTypeCastSegment oDataTypeCastSegment)
|
||||
{
|
||||
targetEntityType = oDataTypeCastSegment.EntityType;
|
||||
|
@ -197,55 +207,16 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
|||
if(navigationProperty != null) {
|
||||
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
// Need to verify that TopSupported or others should be applied to navigation source.
|
||||
// So, how about for the navigation property.
|
||||
OpenApiParameter parameter = Context.CreateTop(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSkip(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSearch(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateFilter(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateCount(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateOrderBy(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSelect(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateExpand(navigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
CreateParametersForAnnotableOfMany(operation, navigationProperty)
|
||||
.Union(
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateOrderBy(navigationProperty),
|
||||
Context.CreateSelect(navigationProperty),
|
||||
Context.CreateExpand(navigationProperty),
|
||||
})
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,6 +233,31 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(entitySet != null)
|
||||
{
|
||||
CreateParametersForAnnotableOfMany(operation, entitySet)
|
||||
.Union(
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateOrderBy(entitySet),
|
||||
Context.CreateSelect(entitySet),
|
||||
Context.CreateExpand(entitySet),
|
||||
})
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
}
|
||||
private IEnumerable<OpenApiParameter> CreateParametersForAnnotableOfMany(OpenApiOperation operation, IEdmVocabularyAnnotatable annotable)
|
||||
{
|
||||
// Need to verify that TopSupported or others should be applied to navigation source.
|
||||
// So, how about for the navigation property.
|
||||
return new OpenApiParameter[] {
|
||||
Context.CreateTop(annotable),
|
||||
Context.CreateSkip(annotable),
|
||||
Context.CreateSearch(annotable),
|
||||
Context.CreateFilter(annotable),
|
||||
Context.CreateCount(annotable),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetSecurity(OpenApiOperation operation)
|
||||
|
|
|
@ -19,8 +19,8 @@ public class ODataTypeCastGetOperationHandlerTests
|
|||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperation(bool enableOperationId)
|
||||
{
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionNavigationProperty(bool enableOperationId)
|
||||
{// ../People/{id}/Friends/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
|
@ -66,7 +66,53 @@ public class ODataTypeCastGetOperationHandlerTests
|
|||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
}
|
||||
//TODO test on entity set
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForEntitySet(bool enableOperationId)
|
||||
{// .../People/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmEntitySet people = model.EntityContainer.FindEntitySet("People");
|
||||
Assert.NotNull(people);
|
||||
|
||||
IEdmEntityType person = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Person");
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(people),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the items of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee in the Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person collection", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(8, operation.Parameters.Count);
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
}
|
||||
//TODO test on cast cast key
|
||||
//TODO test on cast on single nav property
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue