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

Fixes generation of ODataTypeCast paths #212

Merged
merged 12 commits into from
May 9, 2022
4 changes: 1 addition & 3 deletions src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ internal static string ToFirstCharacterLowerCase(this string input)
internal static string NavigationPropertyPath(this ODataPath path, string navigationPropertyName = null)
{
string value = string.Join("/",
path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment
|| s is ODataStreamContentSegment || s is ODataStreamPropertySegment)).Select(e => e.Identifier));

path.Segments.OfType<ODataNavigationPropertySegment>().Select(e => e.Identifier));
return navigationPropertyName == null ? value : $"{value}/{navigationPropertyName}";
}
}
Expand Down
21 changes: 13 additions & 8 deletions src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ private void RetrieveNavigationPropertyPaths(
}
// ~/entityset/{key}/collection-valued-Nav/subtype
// ~/entityset/{key}/single-valued-Nav/subtype
CreateTypeCastPaths(currentPath, convertSettings, navigationProperty.DeclaringType, navigationProperty, targetsMany);
CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, targetsMany);

if ((navSourceRestrictionType?.Referenceable ?? false) ||
(navPropRestrictionType?.Referenceable ?? false))
Expand All @@ -439,7 +439,7 @@ private void RetrieveNavigationPropertyPaths(
currentPath.Push(new ODataKeySegment(navEntityType));
CreateRefPath(currentPath);

CreateTypeCastPaths(currentPath, convertSettings, navigationProperty.DeclaringType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype
CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype
}

// Get possible stream paths for the navigation entity type
Expand All @@ -456,7 +456,7 @@ private void RetrieveNavigationPropertyPaths(
currentPath.Push(new ODataKeySegment(navEntityType));
AppendPath(currentPath.Clone());

CreateTypeCastPaths(currentPath, convertSettings, navigationProperty.DeclaringType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype
CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype
}

// Get possible stream paths for the navigation entity type
Expand Down Expand Up @@ -548,21 +548,26 @@ bool filter(IEdmStructuredType x) =>
.OfType<IEdmStructuredType>()
.ToArray();

foreach(var targetType in targetTypes)
foreach(var targetType in targetTypes)
{
var castPath = currentPath.Clone();
castPath.Push(new ODataTypeCastSegment(targetType));
var targetTypeSegment = new ODataTypeCastSegment(targetType);

castPath.Push(targetTypeSegment);
AppendPath(castPath);
if(targetsMany)
{
CreateCountPath(castPath, convertSettings);
}
else
{
foreach(var declaredNavigationProperty in targetType.DeclaredNavigationProperties())
if (convertSettings.ExpandDerivedTypesNavigationProperties)
{
RetrieveNavigationPropertyPaths(declaredNavigationProperty, null, castPath, convertSettings);
}
foreach (var declaredNavigationProperty in targetType.DeclaredNavigationProperties())
{
RetrieveNavigationPropertyPaths(declaredNavigationProperty, null, castPath, convertSettings);
}
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ public string PathPrefix
/// </summary>
public bool RequireDerivedTypesConstraintForODataTypeCastSegments { get; set; } = true;

/// <summary>
/// Gets/Sets a value indicating whether or not to expand derived types to retrieve their declared navigation properties.
/// </summary>
public bool ExpandDerivedTypesNavigationProperties { get; set; } = true;

/// <summary>
/// Gets/sets a value indicating whether or not to set the deprecated tag for the operation when a revision is present as well as the "x-ms-deprecation" extension with additional information.
/// </summary>
Expand Down Expand Up @@ -275,7 +280,8 @@ internal OpenApiConvertSettings Clone()
AddEnumDescriptionExtension = this.AddEnumDescriptionExtension,
ErrorResponsesAsDefault = this.ErrorResponsesAsDefault,
InnerErrorComplexTypeName = this.InnerErrorComplexTypeName,
RequireRestrictionAnnotationsToGenerateComplexPropertyPaths = this.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths
RequireRestrictionAnnotationsToGenerateComplexPropertyPaths = this.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths,
ExpandDerivedTypesNavigationProperties = this.ExpandDerivedTypesNavigationProperties
};

return newSettings;
Expand Down
4 changes: 3 additions & 1 deletion src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.GetPathItemName(Microsoft.OpenApi.OData.OpenApiConvertSettings settings, System.Collections.Generic.HashSet<string> parameters) -> string
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.GetPathItemName(Microsoft.OpenApi.OData.OpenApiConvertSettings settings, System.Collections.Generic.HashSet<string> parameters) -> string
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Identifier.get -> string
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Kind.get -> Microsoft.OpenApi.OData.Edm.ODataSegmentKind
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.GetAnnotables() -> System.Collections.Generic.IEnumerable<Microsoft.OData.Edm.Vocabularies.IEdmVocabularyAnnotatable>
Microsoft.OpenApi.OData.Common.Utils
Microsoft.OpenApi.OData.Edm.EdmModelExtensions
Microsoft.OpenApi.OData.Edm.EdmTypeExtensions
Microsoft.OpenApi.OData.OpenApiConvertSettings.ExpandDerivedTypesNavigationProperties.get -> bool
Microsoft.OpenApi.OData.OpenApiConvertSettings.ExpandDerivedTypesNavigationProperties.set -> void
Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths.get -> bool
Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireRestrictionAnnotationsToGenerateComplexPropertyPaths.set -> void
static Microsoft.OpenApi.OData.Edm.EdmTypeExtensions.ShouldPathParameterBeQuoted(this Microsoft.OData.Edm.IEdmType edmType, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,18 @@ public void GetPathsForGraphBetaModelReturnsAllPaths()
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
var settings = new OpenApiConvertSettings();
var settings = new OpenApiConvertSettings()
{
ExpandDerivedTypesNavigationProperties = false
};
ODataPathProvider provider = new ODataPathProvider();

// Act
var paths = provider.GetPaths(model, settings);

// Assert
Assert.NotNull(paths);
Assert.Equal(12261, paths.Count());
Assert.Equal(14624, paths.Count());
irvinesunday marked this conversation as resolved.
Show resolved Hide resolved
}

[Fact]
Expand All @@ -59,15 +62,16 @@ public void GetPathsForGraphBetaModelWithDerivedTypesConstraintReturnsAllPaths()
ODataPathProvider provider = new ODataPathProvider();
var settings = new OpenApiConvertSettings
{
RequireDerivedTypesConstraintForBoundOperations = true
RequireDerivedTypesConstraintForBoundOperations = true,
ExpandDerivedTypesNavigationProperties = false
};

// Act
var paths = provider.GetPaths(model, settings);

// Assert
Assert.NotNull(paths);
Assert.Equal(12219, paths.Count());
Assert.Equal(14582, paths.Count());
}

[Fact]
Expand Down Expand Up @@ -102,8 +106,8 @@ public void GetPathsDoesntReturnPathsForCountWhenDisabled()
[InlineData(true, false, false, 7)]
[InlineData(false, true, false, 5)]
[InlineData(false, true, true, 4)]
[InlineData(true, true, true, 5)]
[InlineData(true, true, false, 5)]
[InlineData(true, true, true, 8)]
[InlineData(true, true, false, 8)]
public void GetOperationPathsForModelWithDerivedTypesConstraint(bool addAnnotation, bool getNavPropModel, bool requireConstraint, int expectedCount)
{
// Arrange
Expand All @@ -124,18 +128,16 @@ public void GetOperationPathsForModelWithDerivedTypesConstraint(bool addAnnotati
var dollarCountPathsWithCastSegment = paths.Where(x => x.Kind == ODataPathKind.DollarCount && x.Any(y => y.Kind == ODataSegmentKind.TypeCast));
if(addAnnotation && !getNavPropModel)
Assert.Single(dollarCountPathsWithCastSegment);
else
Assert.Empty(dollarCountPathsWithCastSegment);
}
[Theory]
[InlineData(false, false, true, 4)]
[InlineData(false, false, false, 7)]
[InlineData(true, false, true, 7)]
[InlineData(true, false, false, 7)]
[InlineData(false, true, false, 5)]
[InlineData(false, true, false, 8)]
[InlineData(false, true, true, 5)]
[InlineData(true, true, true, 5)]
[InlineData(true, true, false, 5)]
[InlineData(true, true, true, 8)]
[InlineData(true, true, false, 8)]
public void GetTypeCastPathsForModelWithDerivedTypesConstraint(bool addAnnotation, bool getNavPropModel, bool requireConstraint, int expectedCount)
{
// Arrange
Expand All @@ -154,7 +156,7 @@ public void GetTypeCastPathsForModelWithDerivedTypesConstraint(bool addAnnotatio
Assert.NotNull(paths);
Assert.Equal(expectedCount, paths.Count());
var dollarCountPathsWithCastSegment = paths.Where(x => x.Kind == ODataPathKind.DollarCount && x.Any(y => y.Kind == ODataSegmentKind.TypeCast));
if((addAnnotation || !requireConstraint) && !getNavPropModel)
if(addAnnotation || !requireConstraint)
Assert.Single(dollarCountPathsWithCastSegment);
else
Assert.Empty(dollarCountPathsWithCastSegment);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public void CreateLinksForSingleValuedNavigationProperties()
IEdmModel model = EdmModelHelper.GraphBetaModel;
OpenApiConvertSettings settings = new()
{
ShowLinks = true
ShowLinks = true,
ExpandDerivedTypesNavigationProperties = false
};
ODataContext context = new(model, settings);
IEdmSingleton admin = model.EntityContainer.FindSingleton("admin");
Expand Down Expand Up @@ -70,7 +71,8 @@ public void CreateLinksForCollectionValuedNavigationProperties()
IEdmModel model = EdmModelHelper.GraphBetaModel;
OpenApiConvertSettings settings = new()
{
ShowLinks = true
ShowLinks = true,
ExpandDerivedTypesNavigationProperties = false
};
ODataContext context = new(model, settings);
IEdmSingleton singleton = model.EntityContainer.FindSingleton("admin");
Expand Down Expand Up @@ -137,7 +139,8 @@ public void CreateLinksForSingletons()
IEdmModel model = EdmModelHelper.GraphBetaModel;
OpenApiConvertSettings settings = new()
{
ShowLinks = true
ShowLinks = true,
ExpandDerivedTypesNavigationProperties = false
};
ODataContext context = new(model, settings);
IEdmSingleton singleton = model.EntityContainer.FindSingleton("admin");
Expand Down Expand Up @@ -176,7 +179,8 @@ public void CreateLinksForEntities()
IEdmModel model = EdmModelHelper.GraphBetaModel;
OpenApiConvertSettings settings = new()
{
ShowLinks = true
ShowLinks = true,
ExpandDerivedTypesNavigationProperties = false
};
ODataContext context = new(model, settings);
IEdmEntitySet entityset = model.EntityContainer.FindEntitySet("agreements");
Expand Down