Add Metadata, segment and related path handler and operation handler, expand ODataPath to accept PathTemplate
This commit is contained in:
parent
e1763727f5
commit
aa5b0f0bc7
|
@ -15,6 +15,11 @@ namespace Microsoft.OpenApi.OData.Common
|
|||
/// </summary>
|
||||
public static string ApplicationJsonMediaType = "application/json";
|
||||
|
||||
/// <summary>
|
||||
/// application/xml
|
||||
/// </summary>
|
||||
public static string ApplicationXmlMediaType = "application/xml";
|
||||
|
||||
/// <summary>
|
||||
/// application/octet-stream
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// The $count segment.
|
||||
/// </summary>
|
||||
public class ODataDollarCountSegment : ODataSegment
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override ODataSegmentKind Kind => ODataSegmentKind.DollarCount;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Identifier => "$count";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetPathItemName(OpenApiConvertSettings settings, HashSet<string> parameters) => "$count";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// The $metadata segment.
|
||||
/// </summary>
|
||||
public class ODataMetadataSegment : ODataSegment
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override ODataSegmentKind Kind => ODataSegmentKind.Metadata;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Identifier => "$metadata";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetPathItemName(OpenApiConvertSettings settings, HashSet<string> parameters) => "$metadata";
|
||||
}
|
||||
}
|
|
@ -45,6 +45,17 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the support HttpMethods
|
||||
/// </summary>
|
||||
public ISet<string> HttpMethods { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the path template for this path.
|
||||
/// If it is set, it will be used to generate the path item.
|
||||
/// </summary>
|
||||
public string PathTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments.
|
||||
/// </summary>
|
||||
|
@ -176,6 +187,17 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
internal bool SupportHttpMethod(string method)
|
||||
{
|
||||
// If the Httpmethods is empty, let it go
|
||||
if (HttpMethods.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return HttpMethods.Contains(method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Push a segment to the last.
|
||||
/// </summary>
|
||||
|
@ -243,6 +265,11 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (PathTemplate != null)
|
||||
{
|
||||
return PathTemplate;
|
||||
}
|
||||
|
||||
return "/" + String.Join("/", Segments.Select(e => e.Kind));
|
||||
}
|
||||
|
||||
|
@ -258,6 +285,16 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
|
||||
private ODataPathKind CalcPathType()
|
||||
{
|
||||
if (Segments.Count == 1 && Segments.First().Kind == ODataSegmentKind.Metadata)
|
||||
{
|
||||
return ODataPathKind.Metadata;
|
||||
}
|
||||
|
||||
if (Segments.Last().Kind == ODataSegmentKind.DollarCount)
|
||||
{
|
||||
return ODataPathKind.DollarCount;
|
||||
}
|
||||
|
||||
if (Segments.Any(c => c.Kind == ODataSegmentKind.StreamProperty || c.Kind == ODataSegmentKind.StreamContent))
|
||||
{
|
||||
return ODataPathKind.MediaEntity;
|
||||
|
|
|
@ -50,6 +50,16 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
/// </summary>
|
||||
MediaEntity,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a $metadata path
|
||||
/// </summary>
|
||||
Metadata,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a $count path, for example: ~/customers/$count
|
||||
/// </summary>
|
||||
DollarCount,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an un-supported/unknown path.
|
||||
/// </summary>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
|
@ -14,6 +15,11 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
/// </summary>
|
||||
public enum ODataSegmentKind
|
||||
{
|
||||
/// <summary>
|
||||
/// $metadata
|
||||
/// </summary>
|
||||
Metadata,
|
||||
|
||||
/// <summary>
|
||||
/// Navigation source (entity set or singleton )
|
||||
/// </summary>
|
||||
|
@ -57,7 +63,12 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
/// <summary>
|
||||
/// Stream property
|
||||
/// </summary>
|
||||
StreamProperty
|
||||
StreamProperty,
|
||||
|
||||
/// <summary>
|
||||
/// $count
|
||||
/// </summary>
|
||||
DollarCount,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -42,7 +42,14 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
continue;
|
||||
}
|
||||
|
||||
pathItems.Add(path.GetPathItemName(settings), handler.CreatePathItem(context, path));
|
||||
if (path.PathTemplate != null)
|
||||
{
|
||||
pathItems.Add(path.PathTemplate, handler.CreatePathItem(context, path));
|
||||
}
|
||||
else
|
||||
{
|
||||
pathItems.Add(path.GetPathItemName(settings), handler.CreatePathItem(context, path));
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.ShowRootPath)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve a $count get
|
||||
/// </summary>
|
||||
internal class DollarCountGetOperationHandler : OperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the segment before $count.
|
||||
/// this segment could be "entity set", "Collection property", "Composable function whose return is collection",etc.
|
||||
/// </summary>
|
||||
internal ODataSegment LastSecondSegment { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
base.Initialize(context, path);
|
||||
|
||||
// get the last second segment
|
||||
int count = path.Segments.Count;
|
||||
LastSecondSegment = path.Segments.ElementAt(count - 1);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = $"Get the number of the resource";
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.EnableOperationId)
|
||||
{
|
||||
operation.OperationId = $"Get.Count.{LastSecondSegment.Identifier}";
|
||||
}
|
||||
|
||||
base.SetBasicInfo(operation);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiSchema schema = new OpenApiSchema
|
||||
{
|
||||
Type = "integer",
|
||||
Format = "int32"
|
||||
};
|
||||
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "The count of the resource",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"text/plain",
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = schema
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
|
||||
base.SetResponses(operation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,6 +63,7 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
|
||||
base.SetResponses(operation);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetSecurity(OpenApiOperation operation)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve a metadata document "get"
|
||||
/// </summary>
|
||||
internal class MetadataGetOperationHandler : OperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = $"Get OData metadata (CSDL) document";
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.EnableOperationId)
|
||||
{
|
||||
string routePrefix = Context.Settings.PathPrefix ?? "";
|
||||
if (Context.Settings.PathPrefix != null)
|
||||
{
|
||||
operation.OperationId = $"{routePrefix}.Get.Metadata";
|
||||
}
|
||||
else
|
||||
{
|
||||
operation.OperationId = "Get.Metadata";
|
||||
}
|
||||
}
|
||||
|
||||
base.SetBasicInfo(operation);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiSchema schema = new OpenApiSchema
|
||||
{
|
||||
Type = "string"
|
||||
};
|
||||
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved metadata document",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationXmlMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = schema
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
|
||||
base.SetResponses(operation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,6 +83,18 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
{OperationType.Get, new MediaEntityGetOperationHandler() },
|
||||
{OperationType.Put, new MediaEntityPutOperationHandler() }
|
||||
};
|
||||
|
||||
// $metadata operation (Get)
|
||||
_handlers[ODataPathKind.Metadata] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new MetadataGetOperationHandler() }
|
||||
};
|
||||
|
||||
// $count operation (Get)
|
||||
_handlers[ODataPathKind.DollarCount] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new DollarCountGetOperationHandler() }
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Path item handler for $count.
|
||||
/// </summary>
|
||||
internal class DollarCountPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override ODataPathKind HandleKind => ODataPathKind.DollarCount;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Path item handler for $metadata.
|
||||
/// </summary>
|
||||
internal class MetadataPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override ODataPathKind HandleKind => ODataPathKind.Metadata;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,6 +83,12 @@ namespace Microsoft.OpenApi.OData.PathItem
|
|||
/// <param name="operationType">The operation type.</param>
|
||||
protected virtual void AddOperation(OpenApiPathItem item, OperationType operationType)
|
||||
{
|
||||
string httpMethod = operationType.ToString();
|
||||
if (!Path.SupportHttpMethod(httpMethod))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IOperationHandlerProvider provider = Context.OperationHanderProvider;
|
||||
IOperationHandler operationHander = provider.GetHandler(Path.Kind, operationType);
|
||||
item.AddOperation(operationType, operationHander.CreateOperation(Context, Path));
|
||||
|
|
|
@ -37,7 +37,13 @@ namespace Microsoft.OpenApi.OData.PathItem
|
|||
{ ODataPathKind.Ref, new RefPathItemHandler() },
|
||||
|
||||
// Media Entity
|
||||
{ODataPathKind.MediaEntity, new MediaEntityPathItemHandler() },
|
||||
{ ODataPathKind.MediaEntity, new MediaEntityPathItemHandler() },
|
||||
|
||||
// $Metadata
|
||||
{ ODataPathKind.Metadata, new MetadataPathItemHandler() },
|
||||
|
||||
// $count
|
||||
{ ODataPathKind.DollarCount, new DollarCountPathItemHandler() },
|
||||
|
||||
// Unknown
|
||||
{ ODataPathKind.Unknown, null },
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
|
|||
[InlineData(ODataPathKind.Ref, OperationType.Put, typeof(RefPutOperationHandler))]
|
||||
[InlineData(ODataPathKind.MediaEntity, OperationType.Get, typeof(MediaEntityGetOperationHandler))]
|
||||
[InlineData(ODataPathKind.MediaEntity, OperationType.Put, typeof(MediaEntityPutOperationHandler))]
|
||||
[InlineData(ODataPathKind.Metadata, OperationType.Get, typeof(MetadataGetOperationHandler))]
|
||||
[InlineData(ODataPathKind.DollarCount, OperationType.Get, typeof(DollarCountGetOperationHandler))]
|
||||
public void GetHandlerReturnsCorrectOperationHandlerType(ODataPathKind pathKind, OperationType operationType, Type handlerType)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests
|
|||
[InlineData(ODataPathKind.OperationImport, typeof(OperationImportPathItemHandler))]
|
||||
[InlineData(ODataPathKind.Ref, typeof(RefPathItemHandler))]
|
||||
[InlineData(ODataPathKind.MediaEntity, typeof(MediaEntityPathItemHandler))]
|
||||
[InlineData(ODataPathKind.Metadata, typeof(MetadataPathItemHandler))]
|
||||
[InlineData(ODataPathKind.DollarCount, typeof(DollarCountPathItemHandler))]
|
||||
public void GetHandlerReturnsCorrectHandlerType(ODataPathKind pathKind, Type handlerType)
|
||||
{
|
||||
// Arrange
|
||||
|
|
Loading…
Reference in a new issue