- adds support for singleton downcast

Signed-off-by: Vincent Biret <vibiret@microsoft.com>
This commit is contained in:
Vincent Biret 2021-11-26 14:10:08 -05:00
parent 85fda323ff
commit 26eabeceae
No known key found for this signature in database
GPG key ID: 32426322EDFFB7E3
2 changed files with 91 additions and 10 deletions

View file

@ -34,12 +34,14 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
private bool isKeySegment;
private bool IsSingleElement
{
get => isKeySegment || //TODO add is singleton when implemented
get => isKeySegment ||
singleton != null ||
(navigationProperty != null &&
!navigationProperty.Type.IsCollection() &&
entitySet == null);
}
private NavigationPropertyRestriction restriction;
private IEdmSingleton singleton;
private IEdmEntitySet entitySet;
private IEdmNavigationProperty navigationProperty;
private IEdmEntityType parentEntityType;
@ -60,9 +62,12 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
{
SetNavigationPropertyAndRestrictionFromNavigationSegment(navigationPropertySegment, path);
}
else if(LastSecondSegment is ODataNavigationSourceSegment sourceSegment && sourceSegment.NavigationSource is IEdmEntitySet)
else if(LastSecondSegment is ODataNavigationSourceSegment sourceSegment)
{
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment);
if(sourceSegment.NavigationSource is IEdmEntitySet)
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment);
else if (sourceSegment.NavigationSource is IEdmSingleton)
SetSingletonAndRestrictionFromSourceSegment(sourceSegment);
}
else if(LastSecondSegment is ODataKeySegment)
{
@ -77,7 +82,6 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment1);
}
}
//TODO singleton
if(path.Last() is ODataTypeCastSegment oDataTypeCastSegment)
{
targetEntityType = oDataTypeCastSegment.EntityType;
@ -112,11 +116,26 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
if(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);
}
SetRestrictionFromAnnotable(eSet);
}
}
private void SetSingletonAndRestrictionFromSourceSegment(ODataNavigationSourceSegment sourceSegment)
{
if(sourceSegment.NavigationSource is IEdmSingleton sTon)
{
singleton = sTon;
SetRestrictionFromAnnotable(sTon);
}
}
private void SetRestrictionFromAnnotable(IEdmVocabularyAnnotatable annotable)
{
NavigationRestrictionsType navigation = Context.Model.GetRecord<NavigationRestrictionsType>(annotable, CapabilitiesConstants.NavigationRestrictions);
if (navigation?.RestrictedProperties != null)
{
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty == null);
}
}
@ -337,6 +356,16 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
.ForEach(p => operation.Parameters.Add(p));
}
}
else if(singleton != null)
{
new OpenApiParameter[] {
Context.CreateSelect(singleton),
Context.CreateExpand(singleton),
}
.Where(x => x != null)
.ToList()
.ForEach(p => operation.Parameters.Add(p));
}
}
private IEnumerable<OpenApiParameter> GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
{

View file

@ -238,5 +238,57 @@ public class ODataTypeCastGetOperationHandlerTests
}
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
}
//TODO test on cast singleton
[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForSingleton(bool enableOperationId, bool enablePagination)
{// .../Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
// Arrange
IEdmModel model = EdmModelHelper.TripServiceModel;
OpenApiConvertSettings settings = new()
{
EnableOperationId = enableOperationId,
EnablePagination = enablePagination,
};
ODataContext context = new(model, settings);
IEdmSingleton me = model.EntityContainer.FindSingleton("Me");
Assert.NotNull(me);
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
ODataPath path = new(new ODataNavigationSourceSegment(me),
new ODataTypeCastSegment(employee));
// Act
var operation = _operationHandler.CreateOperation(context, path);
// Assert
Assert.NotNull(operation);
Assert.Equal("Get the item of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person as Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.Summary);
Assert.NotNull(operation.Tags);
var tag = Assert.Single(operation.Tags);
Assert.Equal("Person.Employee", tag.Name);
Assert.Empty(tag.Extensions);
Assert.NotNull(operation.Parameters);
Assert.Equal(2, operation.Parameters.Count); //select, expand
Assert.Null(operation.RequestBody);
if(enablePagination)
Assert.Empty(operation.Extensions);
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);
}
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
}
}