OpenAPI.NET.OData/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
2019-06-25 00:10:05 -07:00

214 lines
7.8 KiB
C#

// ------------------------------------------------------------
// 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.Any;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
namespace Microsoft.OpenApi.OData.Operation
{
/// <summary>
/// Base class for <see cref="OpenApiOperation"/> handler.
/// All derived class should call base method for Set** at the end of override.
/// </summary>
internal abstract class OperationHandler : IOperationHandler
{
/// <inheritdoc/>
public abstract OperationType OperationType { get; }
/// <inheritdoc/>
public virtual OpenApiOperation CreateOperation(ODataContext context, ODataPath path)
{
Context = context ?? throw Error.ArgumentNull(nameof(context));
Path = path ?? throw Error.ArgumentNull(nameof(path));
// Initialize the object ahead.
Initialize(context, path);
OpenApiOperation operation = new OpenApiOperation();
// Description / Summary / OperationId
SetBasicInfo(operation);
// Security
SetSecurity(operation);
// Responses
SetResponses(operation);
// RequestBody
SetRequestBody(operation);
// Parameters
SetParameters(operation);
// Tags
SetTags(operation);
// Extensions
SetExtensions(operation);
return operation;
}
/// <summary>
/// Gets the OData context.
/// </summary>
protected ODataContext Context { get; private set; }
/// <summary>
/// Gets the OData path.
/// </summary>
protected ODataPath Path { get; private set; }
/// <summary>
/// Initialize the handler.
/// It should be call ahead of in derived class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="path">The path.</param>
protected virtual void Initialize(ODataContext context, ODataPath path)
{ }
/// <summary>
/// Set the basic information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetBasicInfo(OpenApiOperation operation)
{ }
/// <summary>
/// Set the security information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetSecurity(OpenApiOperation operation)
{ }
/// <summary>
/// Set the responses information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetResponses(OpenApiOperation operation)
{ }
/// <summary>
/// Set the request body information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetRequestBody(OpenApiOperation operation)
{ }
/// <summary>
/// Set the parameters information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetParameters(OpenApiOperation operation)
{
foreach (ODataKeySegment keySegment in Path.OfType<ODataKeySegment>())
{
foreach (var p in Context.CreateKeyParameters(keySegment))
{
operation.Parameters.Add(p);
}
}
AppendCustomParameters(operation);
}
/// <summary>
/// Set the Tags information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetTags(OpenApiOperation operation)
{
/// The OASIS mapping doc says:
/// The tags array of the Operation Object includes the entity set or singleton name
/// in the first segment of the path template. Additional tag values,
/// e.g. for the entity type of a containment navigation property or the target entity set
/// of a non-containment navigation property, can be included to make this operation more easily discoverable.
/// However, in this SDK, we use the different pattern for the Tags. See each hander.
}
/// <summary>
/// Set the Extensions information for <see cref="OpenApiOperation"/>.
/// </summary>
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
protected virtual void SetExtensions(OpenApiOperation operation)
{ }
/// <summary>
/// Set the <see cref="HttpRequest"/> annotation for the operation.
/// </summary>
/// <param name="operation">The operation.</param>
/// <param name="request">The <see cref="HttpRequest"/>.</param>
protected virtual void AppendCustomParameters(OpenApiOperation operation)
{
}
/// <summary>
/// Set the addition annotation for the response.
/// </summary>
/// <param name="operation">The operation.</param>
/// <param name="request">The <see cref="HttpRequest"/>.</param>
protected virtual void AppendHttpResponses(OpenApiOperation operation)
{
}
/// <summary>
/// Sets the custom parameters.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <param name="customParameters">The custom parameters.</param>
/// <param name="location">The parameter location.</param>
protected static void AppendCustomParameters(IList<OpenApiParameter> parameters, IList<CustomParameter> customParameters, ParameterLocation location)
{
foreach (var param in customParameters)
{
OpenApiParameter parameter = new OpenApiParameter
{
In = location,
Name = param.Name,
Description = param.Description,
Schema = new OpenApiSchema
{
Type = "string"
},
Required = param.Required ?? false
};
if (param.DocumentationURL != null)
{
parameter.Example = new OpenApiString(param.DocumentationURL ?? "N/A");
}
if (param.ExampleValues != null)
{
parameter.Examples = new Dictionary<string, OpenApiExample>();
int index = 1;
foreach (var example in param.ExampleValues)
{
OpenApiExample ex = new OpenApiExample
{
Description = example.Description
};
// maybe call convert to Uri literal
ex.Value = new OpenApiString(example.Value.ToString());
parameter.Examples.Add("example-" + index++, ex);
}
}
parameters.Add(parameter);
}
}
}
}