- fixes #129 a bug where odata count paths would be missing from the description

Signed-off-by: Vincent Biret <vibiret@microsoft.com>
This commit is contained in:
Vincent Biret 2021-11-22 13:37:14 -05:00
parent f08be6482f
commit ae11d65007
No known key found for this signature in database
GPG key ID: 32426322EDFFB7E3
2 changed files with 43 additions and 26 deletions

View file

@ -12,6 +12,10 @@ namespace Microsoft.OpenApi.OData.Edm
/// </summary>
public class ODataDollarCountSegment : ODataSegment
{
/// <summary>
/// Get the static instance of $count segment.
/// </summary>
internal static ODataDollarCountSegment Instance = new();
/// <inheritdoc />
public override ODataSegmentKind Kind => ODataSegmentKind.DollarCount;

View file

@ -102,7 +102,7 @@ namespace Microsoft.OpenApi.OData.Edm
private IEnumerable<ODataPath> MergePaths()
{
List<ODataPath> allODataPaths = new List<ODataPath>();
List<ODataPath> allODataPaths = new();
foreach (var item in _allNavigationSourcePaths.Values)
{
allODataPaths.AddRange(item);
@ -127,6 +127,7 @@ namespace Microsoft.OpenApi.OData.Edm
ODataPathKind kind = path.Kind;
switch(kind)
{
case ODataPathKind.DollarCount:
case ODataPathKind.Entity:
case ODataPathKind.EntitySet:
case ODataPathKind.Singleton:
@ -143,8 +144,7 @@ namespace Microsoft.OpenApi.OData.Edm
case ODataPathKind.NavigationProperty:
case ODataPathKind.Ref:
ODataNavigationPropertySegment navigationPropertySegment = path.Last(p => p is ODataNavigationPropertySegment)
as ODataNavigationPropertySegment;
ODataNavigationPropertySegment navigationPropertySegment = path.OfType<ODataNavigationPropertySegment>().Last();
if (!_allNavigationPropertyPaths.TryGetValue(navigationPropertySegment.EntityType, out IList<ODataPath> npList))
{
@ -174,15 +174,17 @@ namespace Microsoft.OpenApi.OData.Edm
Debug.Assert(navigationSource != null);
// navigation source itself
ODataPath path = new ODataPath(new ODataNavigationSourceSegment(navigationSource));
ODataPath path = new(new ODataNavigationSourceSegment(navigationSource));
AppendPath(path.Clone());
IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
IEdmEntityType entityType = navigationSource.EntityType();
// for entity set, create a path with key
// for entity set, create a path with key and a $count path
if (entitySet != null)
{
CreateCountPath(path);
path.Push(new ODataKeySegment(entityType));
AppendPath(path.Clone());
}
@ -275,6 +277,13 @@ namespace Microsoft.OpenApi.OData.Edm
if (restriction == null || restriction.IndexableByKey == true)
{
IEdmEntityType navEntityType = navigationProperty.ToEntityType();
var targetsMany = navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many;
if (targetsMany)
{
// ~/entityset/{key}/collection-valued-Nav/$count
CreateCountPath(currentPath);
}
if (!navigationProperty.ContainsTarget)
{
@ -283,7 +292,7 @@ namespace Microsoft.OpenApi.OData.Edm
// Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id ={navKey}
CreateRefPath(currentPath);
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
if (targetsMany)
{
// Collection-valued: DELETE ~/entityset/{key}/collection-valued-Nav/{key}/$ref
currentPath.Push(new ODataKeySegment(navEntityType));
@ -296,7 +305,7 @@ namespace Microsoft.OpenApi.OData.Edm
else
{
// append a navigation property key.
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
if (targetsMany)
{
currentPath.Push(new ODataKeySegment(navEntityType));
AppendPath(currentPath.Clone());
@ -318,7 +327,7 @@ namespace Microsoft.OpenApi.OData.Edm
}
}
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
if (targetsMany)
{
currentPath.Pop();
}
@ -360,6 +369,16 @@ namespace Microsoft.OpenApi.OData.Edm
newPath.Push(ODataRefSegment.Instance); // $ref
AppendPath(newPath);
}
/// <summary>
/// Create $count paths.
/// </summary>
/// <param name="currentPath">The current OData path.</param>
private void CreateCountPath(ODataPath currentPath) {
if(currentPath == null) throw new ArgumentNullException(nameof(currentPath));
var countPath = currentPath.Clone();
countPath.Push(ODataDollarCountSegment.Instance);
AppendPath(countPath);
}
/// <summary>
/// Retrieve all bounding <see cref="IEdmOperation"/>.
@ -436,7 +455,11 @@ namespace Microsoft.OpenApi.OData.Edm
}
}
}
private static readonly HashSet<ODataPathKind> _oDataPathKindsToSkipForOperations = new HashSet<ODataPathKind>() {
ODataPathKind.EntitySet,
ODataPathKind.MediaEntity,
ODataPathKind.DollarCount
};
private bool AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType)
{
bool found = false;
@ -448,8 +471,7 @@ namespace Microsoft.OpenApi.OData.Edm
foreach (var subPath in value)
{
if ((isCollection && subPath.Kind == ODataPathKind.EntitySet) ||
(!isCollection && subPath.Kind != ODataPathKind.EntitySet &&
subPath.Kind != ODataPathKind.MediaEntity))
(!isCollection && !_oDataPathKindsToSkipForOperations.Contains(subPath.Kind)))
{
ODataPath newPath = subPath.Clone();
newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction));
@ -461,7 +483,9 @@ namespace Microsoft.OpenApi.OData.Edm
return found;
}
private static readonly HashSet<ODataPathKind> _pathKindToSkipForNavigationProperties = new () {
ODataPathKind.Ref,
};
private bool AppendBoundOperationOnNavigationPropertyPath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType)
{
bool found = false;
@ -469,13 +493,8 @@ namespace Microsoft.OpenApi.OData.Edm
if (_allNavigationPropertyPaths.TryGetValue(bindingEntityType, out IList<ODataPath> value))
{
foreach (var path in value)
foreach (var path in value.Where(x => !_pathKindToSkipForNavigationProperties.Contains(x.Kind)))
{
if (path.Kind == ODataPathKind.Ref)
{
continue;
}
ODataNavigationPropertySegment npSegment = path.Segments.Last(s => s is ODataNavigationPropertySegment) as ODataNavigationPropertySegment;
if (!npSegment.NavigationProperty.ContainsTarget)
@ -596,15 +615,9 @@ namespace Microsoft.OpenApi.OData.Edm
{
if (_allNavigationPropertyPaths.TryGetValue(baseType, out IList<ODataPath> paths))
{
foreach (var path in paths)
foreach (var path in paths.Where(x => !_pathKindToSkipForNavigationProperties.Contains(x.Kind)))
{
if (path.Kind == ODataPathKind.Ref)
{
continue;
}
var npSegment = path.Segments.Last(s => s is ODataNavigationPropertySegment)
as ODataNavigationPropertySegment;
var npSegment = path.Segments.OfType<ODataNavigationPropertySegment>().LastOrDefault();
if (npSegment == null)
{
continue;