- adds support for singleton downcast
Signed-off-by: Vincent Biret <vibiret@microsoft.com>
This commit is contained in:
parent
85fda323ff
commit
26eabeceae
|
@ -34,12 +34,14 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
||||||
private bool isKeySegment;
|
private bool isKeySegment;
|
||||||
private bool IsSingleElement
|
private bool IsSingleElement
|
||||||
{
|
{
|
||||||
get => isKeySegment || //TODO add is singleton when implemented
|
get => isKeySegment ||
|
||||||
|
singleton != null ||
|
||||||
(navigationProperty != null &&
|
(navigationProperty != null &&
|
||||||
!navigationProperty.Type.IsCollection() &&
|
!navigationProperty.Type.IsCollection() &&
|
||||||
entitySet == null);
|
entitySet == null);
|
||||||
}
|
}
|
||||||
private NavigationPropertyRestriction restriction;
|
private NavigationPropertyRestriction restriction;
|
||||||
|
private IEdmSingleton singleton;
|
||||||
private IEdmEntitySet entitySet;
|
private IEdmEntitySet entitySet;
|
||||||
private IEdmNavigationProperty navigationProperty;
|
private IEdmNavigationProperty navigationProperty;
|
||||||
private IEdmEntityType parentEntityType;
|
private IEdmEntityType parentEntityType;
|
||||||
|
@ -60,9 +62,12 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
||||||
{
|
{
|
||||||
SetNavigationPropertyAndRestrictionFromNavigationSegment(navigationPropertySegment, path);
|
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)
|
else if(LastSecondSegment is ODataKeySegment)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +82,6 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
||||||
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment1);
|
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO singleton
|
|
||||||
if(path.Last() is ODataTypeCastSegment oDataTypeCastSegment)
|
if(path.Last() is ODataTypeCastSegment oDataTypeCastSegment)
|
||||||
{
|
{
|
||||||
targetEntityType = oDataTypeCastSegment.EntityType;
|
targetEntityType = oDataTypeCastSegment.EntityType;
|
||||||
|
@ -112,11 +116,26 @@ internal class ODataTypeCastGetOperationHandler : OperationHandler
|
||||||
if(sourceSegment.NavigationSource is IEdmEntitySet eSet)
|
if(sourceSegment.NavigationSource is IEdmEntitySet eSet)
|
||||||
{
|
{
|
||||||
entitySet = eSet;
|
entitySet = eSet;
|
||||||
NavigationRestrictionsType navigation = Context.Model.GetRecord<NavigationRestrictionsType>(eSet, CapabilitiesConstants.NavigationRestrictions);
|
SetRestrictionFromAnnotable(eSet);
|
||||||
if (navigation?.RestrictedProperties != null)
|
}
|
||||||
{
|
}
|
||||||
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty == null);
|
|
||||||
}
|
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));
|
.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)
|
private IEnumerable<OpenApiParameter> GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,5 +238,57 @@ public class ODataTypeCastGetOperationHandlerTests
|
||||||
}
|
}
|
||||||
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue