Merge Graph changes into Master branch
This commit is contained in:
parent
35ec9180e1
commit
1b8d685dc7
|
@ -0,0 +1,23 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthorization"/> provider interface.
|
||||
/// </summary>
|
||||
public interface IAuthorizationProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Provide the <see cref="IAuthorization"/>.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IAuthorization"/>.</returns>
|
||||
//IEnumerable<IAuthorization> GetAuthorizations(IEdmModel model, IEdmVocabularyAnnotatable target);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type Org.OData.Core.V1.CustomParameter
|
||||
/// </summary>
|
||||
internal class CustomParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The Name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The DocumentationURL.
|
||||
/// </summary>
|
||||
public string DocumentationURL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Required.
|
||||
/// </summary>
|
||||
public bool? Required { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ExampleValues.
|
||||
/// </summary>
|
||||
public IEnumerable<Example> ExampleValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="CustomParameter"/>
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
public virtual void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// Name
|
||||
Name = record.GetString("Name");
|
||||
|
||||
// Description
|
||||
Description = record.GetString("Description");
|
||||
|
||||
// DocumentationURL
|
||||
DocumentationURL = record.GetString("DocumentationURL");
|
||||
|
||||
// Required
|
||||
Required = record.GetBoolean("Required");
|
||||
|
||||
// ExampleValues
|
||||
ExampleValues = record.GetCollection("ExampleValues", r =>
|
||||
{
|
||||
IEdmRecordExpression itemRecord = r as IEdmRecordExpression;
|
||||
if (itemRecord != null)
|
||||
{
|
||||
return Example.CreateExample(itemRecord);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
76
src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs
Normal file
76
src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs
Normal file
|
@ -0,0 +1,76 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Org.OData.Core.V1.Example
|
||||
/// </summary>
|
||||
internal abstract class Example
|
||||
{
|
||||
/// <summary>
|
||||
/// Description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="Example"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
public virtual void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// Description
|
||||
Description = record.GetString("Description");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creat the corresponding example object.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
/// <returns>The created example object.</returns>
|
||||
public static Example CreateExample(IEdmRecordExpression record)
|
||||
{
|
||||
if (record == null || record.DeclaredType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IEdmComplexType complexType = record.DeclaredType.Definition as IEdmComplexType;
|
||||
if (complexType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Example example = null;
|
||||
switch (complexType.FullTypeName())
|
||||
{
|
||||
case "Org.OData.Core.V1.ExternalExample":
|
||||
example = new ExternalExample();
|
||||
break;
|
||||
|
||||
case "Org.OData.Core.V1.InlineExample":
|
||||
example = new InlineExample();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (example != null)
|
||||
{
|
||||
example.Init(record);
|
||||
}
|
||||
|
||||
return example;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type Org.OData.Core.V1.ExternalExample
|
||||
/// </summary>
|
||||
internal class ExternalExample : Example
|
||||
{
|
||||
/// <summary>
|
||||
/// ExternalValue
|
||||
/// </summary>
|
||||
public string ExternalValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="ExternalExample"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
base.Init(record);
|
||||
|
||||
// ExternalValue
|
||||
ExternalValue = record.GetString("ExternalValue");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Authorizations;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Org.OData.Core.V1.HttpRequest
|
||||
/// </summary>
|
||||
internal class HttpRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The MethodDescription.
|
||||
/// </summary>
|
||||
public string MethodDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The MethodType.
|
||||
/// </summary>
|
||||
public string MethodType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Custom Query Options.
|
||||
/// </summary>
|
||||
public IList<CustomParameter> CustomQueryOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The custom Headers.
|
||||
/// </summary>
|
||||
public IList<CustomParameter> CustomHeaders { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The http responses.
|
||||
/// </summary>
|
||||
public IList<HttpResponse> HttpResponses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The security sechems.
|
||||
/// </summary>
|
||||
public IList<SecurityScheme> SecuritySchemes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="HttpRequest"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
public virtual void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// Description.
|
||||
Description = record.GetString("Description");
|
||||
|
||||
// MethodDescription.
|
||||
MethodDescription = record.GetString("MethodDescription");
|
||||
|
||||
// MethodType.
|
||||
MethodType = record.GetString("MethodType");
|
||||
|
||||
// CustomQueryOptions
|
||||
CustomQueryOptions = record.GetCollection<CustomParameter>("CustomQueryOptions", (s, r) => s.Init(r as IEdmRecordExpression));
|
||||
|
||||
// CustomHeaders
|
||||
CustomHeaders = record.GetCollection<CustomParameter>("CustomHeaders", (s, r) => s.Init(r as IEdmRecordExpression));
|
||||
|
||||
// HttpResponses
|
||||
HttpResponses = record.GetCollection<HttpResponse>("HttpResponses", (s, r) => s.Init(r as IEdmRecordExpression));
|
||||
|
||||
// SecuritySchemes
|
||||
SecuritySchemes = record.GetCollection<SecurityScheme>("SecuritySchemes", (s, r) => s.Init(r as IEdmRecordExpression));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Org.OData.Core.V1.HttpRequests
|
||||
/// </summary>
|
||||
internal class HttpRequestsAnnotation
|
||||
{
|
||||
/// <summary>
|
||||
/// The Term type name.
|
||||
/// </summary>
|
||||
public virtual string QualifiedName => "Org.OData.Core.V1.HttpRequests";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the http request array.
|
||||
/// </summary>
|
||||
public IList<HttpRequest> Requests { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm mode.
|
||||
/// </summary>
|
||||
public IEdmModel Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vocabulary annotatble.
|
||||
/// </summary>
|
||||
public IEdmVocabularyAnnotatable Target { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="HttpRequestsAnnotation"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
/// <param name="target">The Edm annotation target.</param>
|
||||
public HttpRequestsAnnotation(IEdmModel model, IEdmVocabularyAnnotatable target)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(target, nameof(target));
|
||||
|
||||
Model = model;
|
||||
Target = target;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public HttpRequest GetRequest(string method)
|
||||
{
|
||||
if (Requests == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Requests.FirstOrDefault(e => string.Equals(e.MethodType, method, System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(Target, QualifiedName);
|
||||
if (annotation == null)
|
||||
{
|
||||
IEdmNavigationSource navigationSource = Target as IEdmNavigationSource;
|
||||
|
||||
// if not, search the entity type.
|
||||
if (navigationSource != null)
|
||||
{
|
||||
IEdmEntityType entityType = navigationSource.EntityType();
|
||||
annotation = Model.GetVocabularyAnnotation(entityType, QualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
if (annotation == null ||
|
||||
annotation.Value == null ||
|
||||
annotation.Value.ExpressionKind != EdmExpressionKind.Collection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
|
||||
|
||||
Requests = new List<HttpRequest>();
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
IEdmRecordExpression record = (IEdmRecordExpression)item;
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.Init(record);
|
||||
Requests.Add(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
#if false
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Org.OData.Core.V1.HttpRequests
|
||||
/// </summary>
|
||||
internal class HttpRequestsHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The Term type name.
|
||||
/// </summary>
|
||||
public virtual string QualifiedName => "Org.OData.Core.V1.HttpRequests";
|
||||
|
||||
public IEdmTerm Term { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the http request array.
|
||||
/// </summary>
|
||||
public IDictionary<IEdmVocabularyAnnotatable, IList<HttpRequest> > Requests { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm mode.
|
||||
/// </summary>
|
||||
public IEdmModel Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="HttpRequestsAnnotation"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
public HttpRequestsHelper(IEdmModel model)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Term = model.FindTerm(QualifiedName);
|
||||
Model = model;
|
||||
}
|
||||
|
||||
public HttpRequest GetRequest(string method)
|
||||
{
|
||||
if (Requests == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Requests.FirstOrDefault(e => string.Equals(e.MethodType, method, System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
protected virtual HttpRequest FindRequest(IEdmVocabularyAnnotatable target, string method)
|
||||
{
|
||||
if (Requests == null)
|
||||
{
|
||||
Requests = new Dictionary<IEdmVocabularyAnnotatable, IList<HttpRequest>>();
|
||||
}
|
||||
|
||||
IEdmVocabularyAnnotatable newTarget = target;
|
||||
IEdmNavigationSource navigationSource = target as IEdmNavigationSource;
|
||||
if (navigationSource != null)
|
||||
{
|
||||
newTarget = navigationSource.EntityType();
|
||||
}
|
||||
|
||||
if (Requests.TryGetValue(newTarget, out IList<HttpRequest> values))
|
||||
{
|
||||
return values.FirstOrDefault(e => string.Equals(e.MethodType, method, System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
var annotations = Model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(target, Term);
|
||||
if (annotations != null && annotations.Any())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(Target, QualifiedName);
|
||||
if (annotation == null)
|
||||
{
|
||||
IEdmNavigationSource navigationSource = Target as IEdmNavigationSource;
|
||||
|
||||
// if not, search the entity type.
|
||||
if (navigationSource != null)
|
||||
{
|
||||
IEdmEntityType entityType = navigationSource.EntityType();
|
||||
annotation = Model.GetVocabularyAnnotation(entityType, QualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
if (annotation == null ||
|
||||
annotation.Value == null ||
|
||||
annotation.Value.ExpressionKind != EdmExpressionKind.Collection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
|
||||
|
||||
Requests = new List<HttpRequest>();
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
IEdmRecordExpression record = (IEdmRecordExpression)item;
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.Init(record);
|
||||
Requests.Add(request);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Initialize()
|
||||
{
|
||||
IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(Target, QualifiedName);
|
||||
if (annotation == null)
|
||||
{
|
||||
IEdmNavigationSource navigationSource = Target as IEdmNavigationSource;
|
||||
|
||||
// if not, search the entity type.
|
||||
if (navigationSource != null)
|
||||
{
|
||||
IEdmEntityType entityType = navigationSource.EntityType();
|
||||
annotation = Model.GetVocabularyAnnotation(entityType, QualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
if (annotation == null ||
|
||||
annotation.Value == null ||
|
||||
annotation.Value.ExpressionKind != EdmExpressionKind.Collection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
|
||||
|
||||
Requests = new List<HttpRequest>();
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
IEdmRecordExpression record = (IEdmRecordExpression)item;
|
||||
HttpRequest request = new HttpRequest();
|
||||
request.Init(record);
|
||||
Requests.Add(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// The Org.OData.Core.v1.HttpResponse
|
||||
/// </summary>
|
||||
internal class HttpResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ResponseCode
|
||||
/// </summary>
|
||||
public string ResponseCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Examples
|
||||
/// </summary>
|
||||
public IEnumerable<Example> Examples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Int the <see cref="HttpResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
public void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// ResponseCode
|
||||
ResponseCode = record.GetString("ResponseCode");
|
||||
|
||||
// Description
|
||||
Description = record.GetString("Description");
|
||||
|
||||
// Examples
|
||||
Examples = record.GetCollection("Examples", r =>
|
||||
{
|
||||
IEdmRecordExpression itemRecord = r as IEdmRecordExpression;
|
||||
if (itemRecord != null)
|
||||
{
|
||||
return Example.CreateExample(itemRecord);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type Org.OData.Core.V1.InlineExample
|
||||
/// </summary>
|
||||
internal class InlineExample : Example
|
||||
{
|
||||
/// <summary>
|
||||
/// InlineValue
|
||||
/// </summary>
|
||||
public string InlineValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="InlineExample"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
base.Init(record);
|
||||
|
||||
// InlineValue
|
||||
InlineValue = record.GetString("InlineValue");
|
||||
}
|
||||
}
|
||||
}
|
69
src/Microsoft.OpenApi.OData.Reader/Authorizations/ApiKey.cs
Normal file
69
src/Microsoft.OpenApi.OData.Reader/Authorizations/ApiKey.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum type KeyLocation
|
||||
/// </summary>
|
||||
internal enum KeyLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// API Key is passed in the header.
|
||||
/// </summary>
|
||||
Header,
|
||||
|
||||
/// <summary>
|
||||
/// API Key is passed as a query option.
|
||||
/// </summary>
|
||||
QueryOption,
|
||||
|
||||
/// <summary>
|
||||
/// API Key is passed as a cookie.
|
||||
/// </summary>
|
||||
Cookie
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.ApiKey'
|
||||
/// </summary>
|
||||
internal class ApiKey : Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the header or query parameter.
|
||||
/// </summary>
|
||||
public string KeyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the API Key is passed in the header or as a query option.
|
||||
/// </summary>
|
||||
public KeyLocation? Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the security scheme type.
|
||||
/// </summary>
|
||||
public override SecuritySchemeType SchemeType => SecuritySchemeType.ApiKey;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="ApiKey"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// KeyName.
|
||||
KeyName = record.GetString("KeyName");
|
||||
|
||||
// Location.
|
||||
Location = record.GetEnum<KeyLocation>("Location");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Exceptions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Properties;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract complex type 'Org.OData.Core.V1.Authorization'
|
||||
/// </summary>
|
||||
internal abstract class Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Name that can be used to reference the authorization flow.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Description of the authorization method.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the security scheme type.
|
||||
/// </summary>
|
||||
public abstract SecuritySchemeType SchemeType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="Authorization"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The corresponding record.</param>
|
||||
public virtual void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// Name.
|
||||
Name = record.GetString("Name");
|
||||
|
||||
// Description.
|
||||
Description = record.GetString("Description");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the corresponding Authorization object.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
/// <returns>The created <see cref="Authorization"/> object.</returns>
|
||||
public static Authorization CreateAuthorization(IEdmRecordExpression record)
|
||||
{
|
||||
if (record == null || record.DeclaredType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IEdmComplexType complexType = record.DeclaredType.Definition as IEdmComplexType;
|
||||
if (complexType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Authorization auth = null;
|
||||
switch (complexType.FullTypeName())
|
||||
{
|
||||
case AuthorizationConstants.OpenIDConnect: // OpenIDConnect
|
||||
auth = new OpenIDConnect();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.Http: // Http
|
||||
auth = new Http();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.ApiKey: // ApiKey
|
||||
auth = new ApiKey();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.OAuth2ClientCredentials: // OAuth2ClientCredentials
|
||||
auth = new OAuth2ClientCredentials();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.OAuth2Implicit: // OAuth2Implicit
|
||||
auth = new OAuth2Implicit();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.OAuth2Password: // OAuth2Password
|
||||
auth = new OAuth2Password();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.OAuth2AuthCode: // OAuth2AuthCode
|
||||
auth = new OAuth2AuthCode();
|
||||
break;
|
||||
|
||||
case AuthorizationConstants.OAuthAuthorization: // OAuthAuthorization
|
||||
default:
|
||||
throw new OpenApiException(String.Format(SRResource.AuthorizationRecordTypeNameNotCorrect, complexType.FullTypeName()));
|
||||
}
|
||||
|
||||
if (auth != null)
|
||||
{
|
||||
auth.Init(record);
|
||||
}
|
||||
|
||||
return auth;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant values for Authorization Vocabulary
|
||||
/// </summary>
|
||||
internal class AuthorizationConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// The namespace of Authorization annotation.
|
||||
/// </summary>
|
||||
public const string Namespace = "Org.OData.Authorization.V1";
|
||||
|
||||
/// <summary>
|
||||
/// Term Org.OData.Authorization.V1.Authorizations
|
||||
/// </summary>
|
||||
public const string Authorizations = Namespace + ".Authorizations";
|
||||
|
||||
/// <summary>
|
||||
/// Term Org.OData.Authorization.V1.SecuritySchemes
|
||||
/// </summary>
|
||||
public const string SecuritySchemes = Namespace + ".SecuritySchemes";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OpenIDConnect
|
||||
/// </summary>
|
||||
public const string OpenIDConnect = Namespace + ".OpenIDConnect";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.Http
|
||||
/// </summary>
|
||||
public const string Http = Namespace + ".Http";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.ApiKey
|
||||
/// </summary>
|
||||
public const string ApiKey = Namespace + ".ApiKey";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OAuth2ClientCredentials
|
||||
/// </summary>
|
||||
public const string OAuth2ClientCredentials = Namespace + ".OAuth2ClientCredentials";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OAuth2Implicit
|
||||
/// </summary>
|
||||
public const string OAuth2Implicit = Namespace + ".OAuth2Implicit";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OAuth2Password
|
||||
/// </summary>
|
||||
public const string OAuth2Password = Namespace + ".OAuth2Password";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OAuth2AuthCode
|
||||
/// </summary>
|
||||
public const string OAuth2AuthCode = Namespace + ".OAuth2AuthCode";
|
||||
|
||||
/// <summary>
|
||||
/// Complex type: Org.OData.Authorization.V1.OAuthAuthorization
|
||||
/// </summary>
|
||||
public const string OAuthAuthorization = Namespace + ".OAuthAuthorization";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Abstractions;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// The default 'Org.OData.Core.V1.Authorization' provider.
|
||||
/// </summary>
|
||||
internal class AuthorizationProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IAuthorization"/> collections for a given target in the given Edm model.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IAuthorization"/> collections.</returns>
|
||||
public virtual IEnumerable<Authorization> GetAuthorizations(IEdmModel model, IEdmVocabularyAnnotatable target)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(target, nameof(target));
|
||||
|
||||
// Retrieve it every time when it needed. Don't want to cache the result.
|
||||
return RetrieveAuthorizations(model, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the corresponding Authorization object.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
/// <returns>The created <see cref="Authorization"/> object.</returns>
|
||||
private IEnumerable<Authorization> RetrieveAuthorizations(IEdmModel model, IEdmVocabularyAnnotatable target)
|
||||
{
|
||||
IEdmVocabularyAnnotation annotation = model.GetVocabularyAnnotation(target, AuthorizationConstants.Authorizations);
|
||||
if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection)
|
||||
{
|
||||
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
IEdmRecordExpression record = item as IEdmRecordExpression;
|
||||
if (record == null || record.DeclaredType == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Authorization auth = Authorization.CreateAuthorization(record);
|
||||
if (auth != null)
|
||||
{
|
||||
yield return auth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.AuthorizationScope'
|
||||
/// </summary>
|
||||
internal class AuthorizationScope
|
||||
{
|
||||
/// <summary>
|
||||
/// Scope name.
|
||||
/// </summary>
|
||||
public string Scope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Description of the scope.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="AuthorizationScope"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The corresponding record.</param>
|
||||
public virtual void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// Scope.
|
||||
Scope = record.GetString("Scope");
|
||||
|
||||
// Description.
|
||||
Description = record.GetString("Description");
|
||||
}
|
||||
}
|
||||
}
|
48
src/Microsoft.OpenApi.OData.Reader/Authorizations/Http.cs
Normal file
48
src/Microsoft.OpenApi.OData.Reader/Authorizations/Http.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.Http'
|
||||
/// </summary>
|
||||
internal class Http : Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP Authorization scheme to be used in the Authorization header, as per RFC7235.
|
||||
/// </summary>
|
||||
public string Scheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Format of the bearer token.
|
||||
/// </summary>
|
||||
public string BearerFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the security scheme type.
|
||||
/// </summary>
|
||||
public override SecuritySchemeType SchemeType => SecuritySchemeType.Http;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="Http"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// Scheme
|
||||
Scheme = record.GetString("Scheme");
|
||||
|
||||
// BearerFormat
|
||||
BearerFormat = record.GetString("BearerFormat");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.OAuth2AuthCode'.
|
||||
/// </summary>
|
||||
internal class OAuth2AuthCode : OAuthAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Authorization URL.
|
||||
/// </summary>
|
||||
public string AuthorizationUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Token Url.
|
||||
/// </summary>
|
||||
public string TokenUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OAuth2 type.
|
||||
/// </summary>
|
||||
public override OAuth2Type OAuth2Type => OAuth2Type.AuthCode;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OAuth2AuthCode"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// AuthorizationUrl
|
||||
AuthorizationUrl = record.GetString("AuthorizationUrl");
|
||||
|
||||
// TokenUrl
|
||||
TokenUrl = record.GetString("TokenUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.OAuth2ClientCredentials'
|
||||
/// </summary>
|
||||
internal class OAuth2ClientCredentials : OAuthAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Token Url.
|
||||
/// </summary>
|
||||
public string TokenUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OAuth2 type.
|
||||
/// </summary>
|
||||
public override OAuth2Type OAuth2Type => OAuth2Type.ClientCredentials;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OAuth2ClientCredentials"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// TokenUrl
|
||||
TokenUrl = record.GetString("TokenUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.OAuth2Implicit'
|
||||
/// </summary>
|
||||
internal class OAuth2Implicit : OAuthAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Authorization URL.
|
||||
/// </summary>
|
||||
public string AuthorizationUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OAuth2 type.
|
||||
/// </summary>
|
||||
public override OAuth2Type OAuth2Type => OAuth2Type.Implicit;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OAuth2Implicit"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// AuthorizationUrl
|
||||
AuthorizationUrl = record.GetString("AuthorizationUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.OAuth2Password'
|
||||
/// </summary>
|
||||
internal class OAuth2Password : OAuthAuthorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Token Url.
|
||||
/// </summary>
|
||||
public string TokenUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OAuth2 type.
|
||||
/// </summary>
|
||||
public override OAuth2Type OAuth2Type => OAuth2Type.Pasword;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OAuth2Password"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// TokenUrl
|
||||
TokenUrl = record.GetString("TokenUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// OAuth2 type kind.
|
||||
/// </summary>
|
||||
internal enum OAuth2Type
|
||||
{
|
||||
/// <summary>
|
||||
/// ClientCredentials
|
||||
/// </summary>
|
||||
ClientCredentials,
|
||||
|
||||
/// <summary>
|
||||
/// Implicit
|
||||
/// </summary>
|
||||
Implicit,
|
||||
|
||||
/// <summary>
|
||||
/// Pasword
|
||||
/// </summary>
|
||||
Pasword,
|
||||
|
||||
/// <summary>
|
||||
/// AuthCode
|
||||
/// </summary>
|
||||
AuthCode
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract complex type 'Org.OData.Core.V1.OAuthAuthorization'
|
||||
/// </summary>
|
||||
internal abstract class OAuthAuthorization : Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Available scopes.
|
||||
/// </summary>
|
||||
public IList<AuthorizationScope> Scopes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Refresh Url
|
||||
/// </summary>
|
||||
public string RefreshUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the security scheme type.
|
||||
/// </summary>
|
||||
public override SecuritySchemeType SchemeType => SecuritySchemeType.OAuth2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OAuth2 type.
|
||||
/// </summary>
|
||||
public abstract OAuth2Type OAuth2Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OAuthAuthorization"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// Scopes
|
||||
Scopes = record.GetCollection<AuthorizationScope>("Scopes", (s, item) => s.Init(item as IEdmRecordExpression));
|
||||
|
||||
// RefreshUrl
|
||||
RefreshUrl = record.GetString("RefreshUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type 'Org.OData.Core.V1.OpenIDConnect'
|
||||
/// </summary>
|
||||
internal class OpenIDConnect : Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Issuer location for the OpenID Provider.
|
||||
/// Configuration information can be obtained by appending `/.well-known/openid-configuration` to this Url.
|
||||
/// </summary>
|
||||
public string IssuerUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the security scheme type.
|
||||
/// </summary>
|
||||
public override SecuritySchemeType SchemeType => SecuritySchemeType.OpenIdConnect;
|
||||
|
||||
/// <summary>
|
||||
/// Init <see cref="OpenIDConnect"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">the input record.</param>
|
||||
public override void Init(IEdmRecordExpression record)
|
||||
{
|
||||
// base checked.
|
||||
base.Init(record);
|
||||
|
||||
// IssuerUrl
|
||||
IssuerUrl = record.GetString("IssuerUrl");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// -----------------------------------------------------------
|
||||
// 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.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Authorizations
|
||||
{
|
||||
/// <summary>
|
||||
/// Complex type Org.OData.Core.V1.SecurityScheme
|
||||
/// </summary>
|
||||
internal class SecurityScheme
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of a required authorization scheme.
|
||||
/// </summary>
|
||||
public string AuthorizationSchemeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The names of scopes required from this authorization scheme.
|
||||
/// </summary>
|
||||
public IList<string> RequiredScopes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Init the <see cref="SecurityScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="record">The input record.</param>
|
||||
public void Init(IEdmRecordExpression record)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
|
||||
// AuthorizationSchemeName
|
||||
AuthorizationSchemeName = record.GetString("AuthorizationSchemeName");
|
||||
|
||||
// RequiredScopes
|
||||
RequiredScopes = record.GetCollection("RequiredScopes");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
namespace Microsoft.OpenApi.OData.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Constant strings
|
||||
|
@ -31,8 +31,28 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
public static string StatusCode204 = "204";
|
||||
|
||||
/// <summary>
|
||||
/// Status code: 204
|
||||
/// Status code: default
|
||||
/// </summary>
|
||||
public static string StatusCodeDefault = "default";
|
||||
|
||||
/// <summary>
|
||||
/// extension for toc (table of content) type
|
||||
/// </summary>
|
||||
public static string xMsTocType = "x-ms-docs-toc-type";
|
||||
|
||||
/// <summary>
|
||||
/// extension for key type
|
||||
/// </summary>
|
||||
public static string xMsKeyType = "x-ms-docs-key-type";
|
||||
|
||||
/// <summary>
|
||||
/// extension for operation type
|
||||
/// </summary>
|
||||
public static string xMsDosOperationType = "x-ms-docs-operation-type";
|
||||
|
||||
/// <summary>
|
||||
/// extension for group type
|
||||
/// </summary>
|
||||
public static string xMsDosGroupPath = "x-ms-docs-grouped-path";
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ using System;
|
|||
using System.Globalization;
|
||||
using Microsoft.OpenApi.OData.Properties;
|
||||
|
||||
namespace Microsoft.OpenApi.OData
|
||||
namespace Microsoft.OpenApi.OData.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility class for creating and unwrapping <see cref="Exception"/> instances.
|
||||
|
@ -80,6 +80,29 @@ namespace Microsoft.OpenApi.OData
|
|||
return Error.Argument(parameterName, SRResource.ArgumentNullOrEmpty, parameterName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="InvalidOperationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="messageFormat">A composite format string explaining the reason for the exception.</param>
|
||||
/// <param name="messageArgs">An object array that contains zero or more objects to format.</param>
|
||||
/// <returns>The logged <see cref="Exception"/>.</returns>
|
||||
internal static InvalidOperationException InvalidOperation(string messageFormat, params object[] messageArgs)
|
||||
{
|
||||
return new InvalidOperationException(Error.Format(messageFormat, messageArgs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="InvalidOperationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="innerException">Inner exception</param>
|
||||
/// <param name="messageFormat">A composite format string explaining the reason for the exception.</param>
|
||||
/// <param name="messageArgs">An object array that contains zero or more objects to format.</param>
|
||||
/// <returns>The logged <see cref="Exception"/>.</returns>
|
||||
internal static InvalidOperationException InvalidOperation(Exception innerException, string messageFormat, params object[] messageArgs)
|
||||
{
|
||||
return new InvalidOperationException(Error.Format(messageFormat, messageArgs), innerException);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="NotSupportedException"/>.
|
||||
/// </summary>
|
|
@ -12,6 +12,22 @@ namespace Microsoft.OpenApi.OData.Common
|
|||
/// </summary>
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Upper the first character of the string.
|
||||
/// </summary>
|
||||
/// <param name="input">The input string.</param>
|
||||
/// <returns>The changed string.</returns>
|
||||
public static string UpperFirstChar(string input)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
char first = Char.ToUpper(input[0]);
|
||||
return first + input.Substring(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the input argument whether its value is null or not.
|
||||
/// </summary>
|
||||
|
@ -28,5 +44,21 @@ namespace Microsoft.OpenApi.OData.Common
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check the input string null or empty.
|
||||
/// </summary>
|
||||
/// <param name="value">The input string</param>
|
||||
/// <param name="parameterName">The input parameter name.</param>
|
||||
/// <returns>The input value.</returns>
|
||||
internal static string CheckArgumentNullOrEmpty(string value, string parameterName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(value))
|
||||
{
|
||||
throw Error.ArgumentNullOrEmpty(parameterName);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
150
src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
Normal file
150
src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
Normal file
|
@ -0,0 +1,150 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IEdmModel"/>
|
||||
/// </summary>
|
||||
public static class EdmModelExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the vocabulary annotation from a target annotatable.
|
||||
/// </summary>
|
||||
/// <param name="model">The model referenced to.</param>
|
||||
/// <param name="target">The target Annotatable to find annotation</param>
|
||||
/// <returns>The annotation or null.</returns>
|
||||
public static IEdmVocabularyAnnotation GetVocabularyAnnotation(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(target, nameof(target));
|
||||
Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName));
|
||||
|
||||
IEdmTerm term = model.FindTerm(qualifiedName);
|
||||
if (term != null)
|
||||
{
|
||||
IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(target, term).FirstOrDefault();
|
||||
if (annotation != null)
|
||||
{
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vocabulary annotation from a target annotatable.
|
||||
/// </summary>
|
||||
/// <param name="model">The model referenced to.</param>
|
||||
/// <param name="target">The target Annotatable to find annotation</param>
|
||||
/// <returns>The annotation or null.</returns>
|
||||
public static IEdmVocabularyAnnotation GetVocabularyAnnotation(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(target, nameof(target));
|
||||
Utils.CheckArgumentNull(term, nameof(term));
|
||||
|
||||
IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(target, term).FirstOrDefault();
|
||||
if (annotation != null)
|
||||
{
|
||||
return annotation;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <paramref name="baseType"/> is assignable to <paramref name="subtype"/>.
|
||||
/// In other words, if <paramref name="subtype"/> is a subtype of <paramref name="baseType"/> or not.
|
||||
/// </summary>
|
||||
/// <param name="baseType">Type of the base type.</param>
|
||||
/// <param name="subtype">Type of the sub type.</param>
|
||||
/// <returns>true, if the <paramref name="baseType"/> is assignable to <paramref name="subtype"/>. Otherwise returns false.</returns>
|
||||
public static bool IsAssignableFrom(this IEdmEntityType baseType, IEdmEntityType subtype)
|
||||
{
|
||||
Utils.CheckArgumentNull(baseType, nameof(baseType));
|
||||
Utils.CheckArgumentNull(subtype, nameof(subtype));
|
||||
|
||||
if (baseType.TypeKind != subtype.TypeKind)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subtype.IsEquivalentTo(baseType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IEdmStructuredType structuredSubType = subtype;
|
||||
while (structuredSubType != null)
|
||||
{
|
||||
if (structuredSubType.IsEquivalentTo(baseType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
structuredSubType = structuredSubType.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the operaiton is overload in the model.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
/// <param name="operation">The test operations.</param>
|
||||
/// <returns>True/false.</returns>
|
||||
public static bool IsOperationOverload(this IEdmModel model, IEdmOperation operation)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(operation, nameof(operation));
|
||||
|
||||
return model.SchemaElements.OfType<IEdmOperation>()
|
||||
.Where(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
|
||||
o.Parameters.First().Type.Definition == operation.Parameters.First().Type.Definition
|
||||
).Count() > 1;
|
||||
}
|
||||
|
||||
public static bool IsOperationOverload(this IEdmModel model, IEdmOperationImport operationImport)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(operationImport, nameof(operationImport));
|
||||
|
||||
if (model.EntityContainer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return model.EntityContainer.OperationImports()
|
||||
.Where(o => o.Operation.IsBound == operationImport.Operation.IsBound && o.Name == operationImport.Name).Count() > 1;
|
||||
}
|
||||
|
||||
public static bool IsNavigationTypeOverload(this IEdmModel model, IEdmEntityType entityType, IEdmNavigationProperty navigationProperty)
|
||||
{
|
||||
Utils.CheckArgumentNull(model, nameof(model));
|
||||
Utils.CheckArgumentNull(entityType, nameof(entityType));
|
||||
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
|
||||
|
||||
int count = 0;
|
||||
IEdmEntityType nvaEntityType = navigationProperty.ToEntityType();
|
||||
foreach(var np in entityType.DeclaredNavigationProperties())
|
||||
{
|
||||
if (np.ToEntityType() == nvaEntityType)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count == 0;
|
||||
}
|
||||
}
|
||||
}
|
236
src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
Normal file
236
src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
Normal file
|
@ -0,0 +1,236 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Abstractions;
|
||||
using Microsoft.OpenApi.OData.Annotations;
|
||||
using Microsoft.OpenApi.OData.Authorizations;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
using Microsoft.OpenApi.OData.Operation;
|
||||
using Microsoft.OpenApi.OData.PathItem;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Context information for the <see cref="IEdmModel"/>, configuration, etc.
|
||||
/// </summary>
|
||||
internal class ODataContext
|
||||
{
|
||||
private IDictionary<IEdmTypeReference, IEdmOperation> _boundOperations;
|
||||
private bool _keyAsSegmentSupported = false;
|
||||
private IList<OpenApiTag> _tags = new List<OpenApiTag>();
|
||||
private ODataPathHandler _pathHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
public ODataContext(IEdmModel model)
|
||||
: this(model, new OpenApiConvertSettings())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
/// <param name="settings">The convert setting.</param>
|
||||
public ODataContext(IEdmModel model, OpenApiConvertSettings settings)
|
||||
{
|
||||
Model = model ?? throw Error.ArgumentNull(nameof(model));
|
||||
Settings = settings ?? throw Error.ArgumentNull(nameof(settings));
|
||||
|
||||
EdmModelVisitor visitor = new EdmModelVisitor();
|
||||
visitor.Visit(model);
|
||||
IsSpatialTypeUsed = visitor.IsSpatialTypeUsed;
|
||||
|
||||
_keyAsSegmentSupported = settings.KeyAsSegment ?? model.GetKeyAsSegmentSupported();
|
||||
|
||||
_pathHandler = new ODataPathHandler(this);
|
||||
|
||||
OperationHanderProvider = new OperationHandlerProvider();
|
||||
PathItemHanderProvider = new PathItemHandlerProvider();
|
||||
|
||||
AuthorizationProvider = new AuthorizationProvider();
|
||||
}
|
||||
|
||||
public IPathItemHandlerProvider PathItemHanderProvider { get; }
|
||||
|
||||
public IOperationHandlerProvider OperationHanderProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IAuthorizationProvider"/> to provider the authorization.
|
||||
/// </summary>
|
||||
public AuthorizationProvider AuthorizationProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm model.
|
||||
/// </summary>
|
||||
public IEdmModel Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Entity Container.
|
||||
/// </summary>
|
||||
public IEdmEntityContainer EntityContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model.EntityContainer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ODataPath"/>s.
|
||||
/// </summary>
|
||||
public IList<ODataPath> Paths => _pathHandler.Paths;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the boolean value indicating to support key as segment.
|
||||
/// </summary>
|
||||
public bool KeyAsSegment => _keyAsSegmentSupported;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value indicating the Edm spatial type used.
|
||||
/// </summary>
|
||||
public bool IsSpatialTypeUsed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the convert settings.
|
||||
/// </summary>
|
||||
public OpenApiConvertSettings Settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bound operations (functions & actions).
|
||||
/// </summary>
|
||||
public IDictionary<IEdmTypeReference, IEdmOperation> BoundOperations
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_boundOperations == null)
|
||||
{
|
||||
GenerateBoundOperations();
|
||||
}
|
||||
|
||||
return _boundOperations;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the operations using the <see cref="IEdmEntityType"/>
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <param name="collection">The collection flag.</param>
|
||||
/// <returns>The found operations.</returns>
|
||||
public IEnumerable<Tuple<IEdmEntityType, IEdmOperation>> FindOperations(IEdmEntityType entityType, bool collection)
|
||||
{
|
||||
Utils.CheckArgumentNull(entityType, nameof(entityType));
|
||||
|
||||
string fullTypeName = collection ?
|
||||
"Collection(" + entityType.FullName() + ")" :
|
||||
entityType.FullName();
|
||||
|
||||
foreach (var item in BoundOperations)
|
||||
{
|
||||
IEdmEntityType operationBindingType;
|
||||
if (collection)
|
||||
{
|
||||
if (!item.Key.IsCollection())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
operationBindingType = item.Key.AsCollection().ElementType().AsEntity().EntityDefinition();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.Key.IsCollection())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
operationBindingType = item.Key.AsEntity().EntityDefinition();
|
||||
}
|
||||
|
||||
if (entityType.IsAssignableFrom(operationBindingType))
|
||||
{
|
||||
yield return Tuple.Create(operationBindingType, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary<IEdmVocabularyAnnotatable, HttpRequestsAnnotation> _requests;
|
||||
|
||||
public HttpRequest FindRequest(IEdmVocabularyAnnotatable target, string method)
|
||||
{
|
||||
if (_requests == null)
|
||||
{
|
||||
_requests = new Dictionary<IEdmVocabularyAnnotatable, HttpRequestsAnnotation>();
|
||||
}
|
||||
|
||||
if (!_requests.TryGetValue(target, out HttpRequestsAnnotation value))
|
||||
{
|
||||
value = new HttpRequestsAnnotation(Model, target);
|
||||
_requests.Add(target, value);
|
||||
}
|
||||
|
||||
return value.GetRequest(method);
|
||||
}
|
||||
|
||||
private void GenerateBoundOperations()
|
||||
{
|
||||
if (_boundOperations != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_boundOperations = new Dictionary<IEdmTypeReference, IEdmOperation>();
|
||||
foreach (var edmOperation in Model.SchemaElements.OfType<IEdmOperation>().Where(e => e.IsBound))
|
||||
{
|
||||
IEdmOperationParameter bindingParameter = edmOperation.Parameters.First();
|
||||
_boundOperations.Add(bindingParameter.Type, edmOperation);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<OpenApiTag> Tags
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tags;
|
||||
}
|
||||
}
|
||||
|
||||
public void AppendTag(OpenApiTag tagItem)
|
||||
{
|
||||
if (_tags.Any(c => c.Name == tagItem.Name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_tags.Add(tagItem);
|
||||
}
|
||||
|
||||
private IDictionary<string, int> _cached1 = new Dictionary<string, int>();
|
||||
public int GetIndex(string source)
|
||||
{
|
||||
if (_cached1.TryGetValue(source, out int value))
|
||||
{
|
||||
_cached1[source]++;
|
||||
return _cached1[source];
|
||||
}
|
||||
else
|
||||
{
|
||||
_cached1[source] = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs
Normal file
53
src/Microsoft.OpenApi.OData.Reader/Edm/ODataKeySegment.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// The key segment.
|
||||
/// </summary>
|
||||
public class ODataKeySegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataKeySegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type contains the keys.</param>
|
||||
public ODataKeySegment(IEdmEntityType entityType)
|
||||
{
|
||||
EntityType = entityType ?? throw Error.ArgumentNull(nameof(entityType));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
IList<IEdmStructuralProperty> keys = EntityType.Key().ToList();
|
||||
if (keys.Count() == 1)
|
||||
{
|
||||
return "{" + keys.First().Name + "}";
|
||||
}
|
||||
else
|
||||
{
|
||||
IList<string> keyStrings = new List<string>();
|
||||
foreach (var keyProperty in keys)
|
||||
{
|
||||
keyStrings.Add(keyProperty.Name + "={" + keyProperty.Name + "}");
|
||||
}
|
||||
return "{" + String.Join(",", keyStrings) + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Navigation property segment.
|
||||
/// </summary>
|
||||
public class ODataNavigationPropertySegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataNavigationPropertySegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="navigationProperty"></param>
|
||||
public ODataNavigationPropertySegment(IEdmNavigationProperty navigationProperty)
|
||||
{
|
||||
NavigationProperty = navigationProperty ?? throw Error.ArgumentNull(nameof(navigationProperty));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the navigation property.
|
||||
/// </summary>
|
||||
public IEdmNavigationProperty NavigationProperty { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType => NavigationProperty.ToEntityType();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => NavigationProperty.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return NavigationProperty.Name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Navigation source (entity set or singleton) segment.
|
||||
/// </summary>
|
||||
public class ODataNavigationSourceSegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataNavigationSourceSegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="navigaitonSource">The navigation source.</param>
|
||||
public ODataNavigationSourceSegment(IEdmNavigationSource navigaitonSource)
|
||||
{
|
||||
NavigationSource = navigaitonSource ?? throw Error.ArgumentNull(nameof(navigaitonSource));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the navigation source.
|
||||
/// </summary>
|
||||
public IEdmNavigationSource NavigationSource { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType => NavigationSource.EntityType();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => NavigationSource.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return NavigationSource.Name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Operation import segment.
|
||||
/// </summary>
|
||||
public class ODataOperationImportSegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataOperationImportSegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="operationImport">The operation import.</param>
|
||||
public ODataOperationImportSegment(IEdmOperationImport operationImport)
|
||||
{
|
||||
OperationImport = operationImport ?? throw Error.ArgumentNull(nameof(operationImport));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the operation import.
|
||||
/// </summary>
|
||||
public IEdmOperationImport OperationImport { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => OperationImport.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return OperationImport.Name;
|
||||
}
|
||||
}
|
||||
}
|
110
src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs
Normal file
110
src/Microsoft.OpenApi.OData.Reader/Edm/ODataOperationSegment.cs
Normal file
|
@ -0,0 +1,110 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Operation segment
|
||||
/// </summary>
|
||||
public class ODataOperationSegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataOperationSegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation.</param>
|
||||
public ODataOperationSegment(IEdmOperation operation)
|
||||
: this(operation, true)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataOperationSegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation.</param>
|
||||
/// <param name="unqualifiedCall">The unqualified call.</param>
|
||||
public ODataOperationSegment(IEdmOperation operation, bool unqualifiedCall)
|
||||
{
|
||||
Operation = operation ?? throw Error.ArgumentNull(nameof(operation));
|
||||
UnqualifiedCall = unqualifiedCall;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the operation.
|
||||
/// </summary>
|
||||
public IEdmOperation Operation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unqualified call.
|
||||
/// </summary>
|
||||
public bool UnqualifiedCall { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => Operation.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
if (Operation.IsFunction())
|
||||
{
|
||||
return FunctionName(Operation as IEdmFunction);
|
||||
}
|
||||
|
||||
return ActionName(Operation as IEdmAction);
|
||||
}
|
||||
|
||||
private string FunctionName(IEdmFunction function)
|
||||
{
|
||||
StringBuilder functionName = new StringBuilder();
|
||||
if (UnqualifiedCall)
|
||||
{
|
||||
functionName.Append(function.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
functionName.Append(function.FullName());
|
||||
}
|
||||
functionName.Append("(");
|
||||
|
||||
// Structured or collection-valued parameters are represented as a parameter alias in the path template
|
||||
// and the parameters array contains a Parameter Object for the parameter alias as a query option of type string.
|
||||
int skip = function.IsBound ? 1 : 0;
|
||||
functionName.Append(String.Join(",", function.Parameters.Skip(skip).Select(p =>
|
||||
{
|
||||
if (p.Type.IsStructured() || p.Type.IsCollection())
|
||||
{
|
||||
return p.Name + "=@" + p.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return p.Name + "={" + p.Name + "}";
|
||||
}
|
||||
})));
|
||||
|
||||
functionName.Append(")");
|
||||
|
||||
return functionName.ToString();
|
||||
}
|
||||
|
||||
private string ActionName(IEdmAction action)
|
||||
{
|
||||
if (UnqualifiedCall)
|
||||
{
|
||||
return action.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return action.FullName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
217
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs
Normal file
217
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs
Normal file
|
@ -0,0 +1,217 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes an OData path.
|
||||
/// </summary>
|
||||
public class ODataPath : IEnumerable<ODataSegment>
|
||||
{
|
||||
private ODataPathType? _pathType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataPath"/> class.
|
||||
/// </summary>
|
||||
/// <param name="segments">The segments.</param>
|
||||
public ODataPath(IEnumerable<ODataSegment> segments)
|
||||
{
|
||||
Segments = segments.ToList();
|
||||
if (Segments.Any(s => s == null))
|
||||
{
|
||||
throw Error.ArgumentNull("segments");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="ODataPath"/> containing the given segments.
|
||||
/// </summary>
|
||||
/// <param name="segments">The segments that make up the path.</param>
|
||||
/// <exception cref="ArgumentNullException">Throws if input segments is null.</exception>
|
||||
public ODataPath(params ODataSegment[] segments)
|
||||
: this((IEnumerable<ODataSegment>)segments)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the segments.
|
||||
/// </summary>
|
||||
public IList<ODataSegment> Segments { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Pop the last segment.
|
||||
/// </summary>
|
||||
/// <returns>The pop last segment.</returns>
|
||||
public ODataSegment Pop()
|
||||
{
|
||||
if (!Segments.Any())
|
||||
{
|
||||
throw Error.InvalidOperation("Pop a segment is invalid. The segments in the path is empty.");
|
||||
}
|
||||
|
||||
ODataSegment segment = Segments.Last();
|
||||
Segments.RemoveAt(Segments.Count - 1);
|
||||
return segment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Push a segment to the last.
|
||||
/// </summary>
|
||||
/// <param name="segment">The pushed segment.</param>
|
||||
/// <returns>The whole path object.</returns>
|
||||
public ODataPath Push(ODataSegment segment)
|
||||
{
|
||||
if (Segments == null)
|
||||
{
|
||||
Segments = new List<ODataSegment>();
|
||||
}
|
||||
|
||||
Segments.Add(segment);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first segment in the path. Returns null if the path is empty.
|
||||
/// </summary>
|
||||
public ODataSegment FirstSegment
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Segments.Count == 0 ? null : this.Segments[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the last segment in the path. Returns null if the path is empty.
|
||||
/// </summary>
|
||||
public ODataSegment LastSegment
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Segments.Count == 0 ? null : this.Segments[this.Segments.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of segments in this path.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return this.Segments.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the segments enumerator
|
||||
/// </summary>
|
||||
/// <returns>The segments enumerator</returns>
|
||||
public IEnumerator<ODataSegment> GetEnumerator()
|
||||
{
|
||||
return this.Segments.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the segments enumerator
|
||||
/// </summary>
|
||||
/// <returns>The segments enumerator.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clone a new ODataPath object.
|
||||
/// </summary>
|
||||
/// <returns>The new ODataPath.</returns>
|
||||
public ODataPath Clone()
|
||||
{
|
||||
return new ODataPath(Segments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the segment count.
|
||||
/// </summary>
|
||||
/// <param name="keySegmentAsDepth">A bool value indicating whether to count key segment or not.</param>
|
||||
/// <returns>The count.</returns>
|
||||
public int GetCount(bool keySegmentAsDepth)
|
||||
{
|
||||
return Segments.Count(c => keySegmentAsDepth ? true : !(c is ODataKeySegment));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output the path string.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return "/" + String.Join("/", Segments);
|
||||
}
|
||||
|
||||
internal ODataPathType PathType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pathType == null)
|
||||
{
|
||||
CalcPathType();
|
||||
}
|
||||
|
||||
return _pathType.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalcPathType()
|
||||
{
|
||||
if (Segments.Any(c => c is ODataNavigationPropertySegment))
|
||||
{
|
||||
_pathType = ODataPathType.NavigationProperty;
|
||||
return;
|
||||
}
|
||||
else if (Segments.Any(c => c is ODataOperationImportSegment))
|
||||
{
|
||||
_pathType = ODataPathType.OperationImport;
|
||||
return;
|
||||
}
|
||||
else if (Segments.Any(c => c is ODataOperationSegment))
|
||||
{
|
||||
_pathType = ODataPathType.Operation;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Segments.Count == 1)
|
||||
{
|
||||
ODataNavigationSourceSegment segment = Segments[0] as ODataNavigationSourceSegment;
|
||||
if (segment == null)
|
||||
{
|
||||
throw Error.ArgumentNull("segment");
|
||||
}
|
||||
|
||||
if (segment.NavigationSource is IEdmSingleton)
|
||||
{
|
||||
_pathType = ODataPathType.Singleton;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pathType = ODataPathType.EntitySet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Segments.Count != 2)
|
||||
{
|
||||
throw Error.InvalidOperation("Calc the path type wrong!");
|
||||
}
|
||||
|
||||
_pathType = ODataPathType.Entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
269
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathHandler.cs
Normal file
269
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathHandler.cs
Normal file
|
@ -0,0 +1,269 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for <see cref="ODataPath"/> generating.
|
||||
/// </summary>
|
||||
internal class ODataPathHandler
|
||||
{
|
||||
private IList<ODataPath> _paths = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OData Context
|
||||
/// </summary>
|
||||
public ODataContext Context { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ODataPath"/>s.
|
||||
/// </summary>
|
||||
public IList<ODataPath> Paths => GeneratePaths();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataPathHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
public ODataPathHandler(ODataContext context)
|
||||
{
|
||||
Context = context ?? throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the <see cref="ODataPath"/> from <see cref="IEdmModel"/> and <see cref="OpenApiConvertSettings"/>.
|
||||
/// </summary>
|
||||
/// <returns>The generated paths.</returns>
|
||||
private IList<ODataPath> GeneratePaths()
|
||||
{
|
||||
if (_paths != null)
|
||||
{
|
||||
return _paths;
|
||||
}
|
||||
|
||||
_paths = new List<ODataPath>();
|
||||
if (Context.Model.EntityContainer == null)
|
||||
{
|
||||
return _paths;
|
||||
}
|
||||
|
||||
// entity set
|
||||
foreach (IEdmEntitySet entitySet in Context.Model.EntityContainer.EntitySets())
|
||||
{
|
||||
RetrieveNavigationSourcePaths(entitySet);
|
||||
|
||||
if (Context.Settings.EnableOperationPath)
|
||||
{
|
||||
RetrieveOperationPaths(entitySet);
|
||||
}
|
||||
}
|
||||
|
||||
// singleton
|
||||
foreach (IEdmSingleton singleton in Context.Model.EntityContainer.Singletons())
|
||||
{
|
||||
RetrieveNavigationSourcePaths(singleton);
|
||||
|
||||
if (Context.Settings.EnableOperationPath)
|
||||
{
|
||||
RetrieveOperationPaths(singleton);
|
||||
}
|
||||
}
|
||||
|
||||
// operation import
|
||||
if (Context.Settings.EnableOperationImportPath)
|
||||
{
|
||||
foreach (IEdmOperationImport import in Context.Model.EntityContainer.OperationImports())
|
||||
{
|
||||
_paths.Add(new ODataPath(new ODataOperationImportSegment(import)));
|
||||
}
|
||||
}
|
||||
|
||||
return _paths;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the path for <see cref="IEdmNavigationSource"/>.
|
||||
/// </summary>
|
||||
/// <param name="navigationSource">The navigation source.</param>
|
||||
private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource)
|
||||
{
|
||||
Debug.Assert(navigationSource != null);
|
||||
|
||||
// navigation source itself
|
||||
ODataPath path = new ODataPath();
|
||||
path.Push(new ODataNavigationSourceSegment(navigationSource));
|
||||
_paths.Add(path.Clone());
|
||||
|
||||
IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
|
||||
IEdmEntityType entityType = navigationSource.EntityType();
|
||||
|
||||
// for entity set, create a path with key
|
||||
if (entitySet != null)
|
||||
{
|
||||
path.Push(new ODataKeySegment(entityType));
|
||||
_paths.Add(path.Clone());
|
||||
}
|
||||
|
||||
// navigation property
|
||||
if (Context.Settings.EnableNavigationPropertyPath)
|
||||
{
|
||||
foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties())
|
||||
{
|
||||
RetrieveNavigationPropertyPaths(np, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (entitySet != null)
|
||||
{
|
||||
path.Pop(); // end of entity
|
||||
}
|
||||
path.Pop(); // end of navigation source.
|
||||
Debug.Assert(path.Any() == false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the path for <see cref="IEdmNavigationProperty"/>.
|
||||
/// </summary>
|
||||
/// <param name="navigationProperty">The navigation property.</param>
|
||||
/// <param name="currentPath">The current OData path.</param>
|
||||
private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationProperty, ODataPath currentPath)
|
||||
{
|
||||
Debug.Assert(navigationProperty != null);
|
||||
Debug.Assert(currentPath != null);
|
||||
|
||||
int count = currentPath.GetCount(Context.Settings.CountKeySegmentAsDepth);
|
||||
if (count > Context.Settings.NavigationPropertyDepth)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldExpand = ShouldExpandNavigationProperty(navigationProperty, currentPath);
|
||||
|
||||
// append a navigation property.
|
||||
currentPath.Push(new ODataNavigationPropertySegment(navigationProperty));
|
||||
_paths.Add(currentPath.Clone());
|
||||
|
||||
// append a navigation property key.
|
||||
IEdmEntityType navEntityType = navigationProperty.ToEntityType();
|
||||
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
currentPath.Push(new ODataKeySegment(navEntityType));
|
||||
_paths.Add(currentPath.Clone());
|
||||
}
|
||||
|
||||
if (shouldExpand)
|
||||
{
|
||||
foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties())
|
||||
{
|
||||
RetrieveNavigationPropertyPaths(subNavProperty, currentPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
currentPath.Pop();
|
||||
}
|
||||
|
||||
currentPath.Pop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the <see cref="IEdmOperation"/> path for <see cref="IEdmNavigationSource"/>.
|
||||
/// </summary>
|
||||
/// <param name="navigationSource">The navigation source.</param>
|
||||
private void RetrieveOperationPaths(IEdmNavigationSource navigationSource)
|
||||
{
|
||||
Debug.Assert(navigationSource != null);
|
||||
|
||||
IEnumerable<Tuple<IEdmEntityType, IEdmOperation>> operations;
|
||||
IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
|
||||
|
||||
ODataPath path = new ODataPath(new ODataNavigationSourceSegment(navigationSource));
|
||||
|
||||
if (entitySet != null)
|
||||
{
|
||||
operations = Context.FindOperations(navigationSource.EntityType(), collection: true);
|
||||
foreach (var operation in operations)
|
||||
{
|
||||
// Append the type cast
|
||||
if (!operation.Item1.IsEquivalentTo(navigationSource.EntityType()))
|
||||
{
|
||||
path.Push(new ODataTypeCastSegment(operation.Item1));
|
||||
path.Push(new ODataOperationSegment(operation.Item2, Context.Settings.UnqualifiedCall));
|
||||
_paths.Add(path.Clone());
|
||||
path.Pop();
|
||||
path.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Push(new ODataOperationSegment(operation.Item2, Context.Settings.UnqualifiedCall));
|
||||
_paths.Add(path.Clone());
|
||||
path.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for single
|
||||
if (entitySet != null)
|
||||
{
|
||||
path.Push(new ODataKeySegment(navigationSource.EntityType()));
|
||||
}
|
||||
|
||||
operations = Context.FindOperations(navigationSource.EntityType(), collection: false);
|
||||
foreach (var operation in operations)
|
||||
{
|
||||
// Append the type cast
|
||||
if (!operation.Item1.IsEquivalentTo(navigationSource.EntityType()))
|
||||
{
|
||||
path.Push(new ODataTypeCastSegment(operation.Item1));
|
||||
path.Push(new ODataOperationSegment(operation.Item2, Context.Settings.UnqualifiedCall));
|
||||
_paths.Add(path.Clone());
|
||||
path.Pop();
|
||||
path.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Push(new ODataOperationSegment(operation.Item2, Context.Settings.UnqualifiedCall));
|
||||
_paths.Add(path.Clone());
|
||||
path.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (entitySet != null)
|
||||
{
|
||||
path.Pop();
|
||||
}
|
||||
|
||||
path.Pop();
|
||||
|
||||
Debug.Assert(path.Any() == false);
|
||||
}
|
||||
|
||||
private static bool ShouldExpandNavigationProperty(IEdmNavigationProperty navigationProperty, ODataPath currentPath)
|
||||
{
|
||||
if (!navigationProperty.ContainsTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IEdmEntityType navEntityType = navigationProperty.ToEntityType();
|
||||
foreach (ODataSegment segment in currentPath)
|
||||
{
|
||||
if (navEntityType.IsAssignableFrom(segment.EntityType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
43
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathType.cs
Normal file
43
src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathType.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum types for Edm path.
|
||||
/// </summary>
|
||||
public enum ODataPathType
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entity set path. for example: ~/users
|
||||
/// </summary>
|
||||
EntitySet,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entity path, for example: ~/users/{id}
|
||||
/// </summary>
|
||||
Entity,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a singleton path, for example: ~/me
|
||||
/// </summary>
|
||||
Singleton,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an operation (function or action) path, for example: ~/users/NS.findRooms(roomId={roomId})
|
||||
/// </summary>
|
||||
Operation,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an operation import (function import or action import path), for example: ~/ResetData
|
||||
/// </summary>
|
||||
OperationImport,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an navigation propert path, for example: ~/users/{id}/onedrive
|
||||
/// </summary>
|
||||
NavigationProperty
|
||||
}
|
||||
}
|
25
src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs
Normal file
25
src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs
Normal file
|
@ -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.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an OData segment. For example, an entity set segment.
|
||||
/// </summary>
|
||||
public abstract class ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entity type of current segment.
|
||||
/// </summary>
|
||||
public abstract IEdmEntityType EntityType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ges the name of this segment.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Type cast segment.
|
||||
/// </summary>
|
||||
public class ODataTypeCastSegment : ODataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataTypeCastSegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The type cast type.</param>
|
||||
public ODataTypeCastSegment(IEdmEntityType entityType)
|
||||
{
|
||||
EntityType = entityType ?? throw Error.ArgumentNull(nameof(entityType));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IEdmEntityType EntityType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return EntityType.FullTypeName();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => EntityType.FullTypeName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IEdmRecordExpression"/>
|
||||
/// </summary>
|
||||
internal static class RecordExpressionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the string value of a property in the given record expression.
|
||||
/// </summary>
|
||||
/// <param name="record">The given record.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The property string value.</returns>
|
||||
public static string GetString(this IEdmRecordExpression record, string propertyName)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
if (record.Properties != null)
|
||||
{
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmStringConstantExpression value = property.Value as IEdmStringConstantExpression;
|
||||
if (value != null)
|
||||
{
|
||||
return value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the boolean value from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The boolean value or null.</returns>
|
||||
public static bool? GetBoolean(this IEdmRecordExpression record, string propertyName)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
if (record.Properties != null)
|
||||
{
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmBooleanConstantExpression value = property.Value as IEdmBooleanConstantExpression;
|
||||
if (value != null)
|
||||
{
|
||||
return value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Enum value from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The output enum type.</typeparam>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The Enum value or null.</returns>
|
||||
public static T? GetEnum<T>(this IEdmRecordExpression record, string propertyName)
|
||||
where T : struct
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
if (record.Properties != null)
|
||||
{
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmEnumMemberExpression value = property.Value as IEdmEnumMemberExpression;
|
||||
if (value != null && value.EnumMembers != null && value.EnumMembers.Any())
|
||||
{
|
||||
IEdmEnumMember member = value.EnumMembers.First();
|
||||
T result;
|
||||
if (Enum.TryParse(member.Name, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the property path from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The property path or null.</returns>
|
||||
public static string GetPropertyPath(this IEdmRecordExpression record, string propertyName)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
if (record.Properties != null)
|
||||
{
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmPathExpression value = property.Value as IEdmPathExpression;
|
||||
if (value != null)
|
||||
{
|
||||
return value.Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the collection of property path from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The collection of property path or null.</returns>
|
||||
public static IList<string> GetCollectionPropertyPath(this IEdmRecordExpression record, string propertyName)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
if (record.Properties != null)
|
||||
{
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmCollectionExpression value = property.Value as IEdmCollectionExpression;
|
||||
if (value != null && value.Elements != null)
|
||||
{
|
||||
IList<string> properties = new List<string>();
|
||||
foreach (var a in value.Elements.Select(e => e as IEdmPathExpression))
|
||||
{
|
||||
properties.Add(a.Path);
|
||||
}
|
||||
|
||||
if (properties.Any())
|
||||
{
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the collection of <typeparamref name="T"/> from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The element type.</typeparam>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <param name="elementAction">The element action.</param>
|
||||
/// <returns>The collection or null.</returns>
|
||||
public static IList<T> GetCollection<T>(this IEdmRecordExpression record, string propertyName, Action<T, IEdmExpression> elementAction)
|
||||
where T: new()
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmCollectionExpression collection = property.Value as IEdmCollectionExpression;
|
||||
if (collection != null && collection.Elements != null)
|
||||
{
|
||||
IList<T> items = new List<T>();
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
T a = new T();
|
||||
elementAction(a, item);
|
||||
items.Add(a);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCollection<T>(this IEdmRecordExpression record, string propertyName, Func<IEdmExpression, T> elementFunc)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmCollectionExpression collection = property.Value as IEdmCollectionExpression;
|
||||
if (collection != null && collection.Elements != null)
|
||||
{
|
||||
return collection.Elements.Select(e => elementFunc(e));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the collection of string from the record using the given property name.
|
||||
/// </summary>
|
||||
/// <param name="record">The record expression.</param>
|
||||
/// <param name="propertyName">The property name.</param>
|
||||
/// <returns>The collection of string or null.</returns>
|
||||
public static IList<string> GetCollection(this IEdmRecordExpression record, string propertyName)
|
||||
{
|
||||
Utils.CheckArgumentNull(record, nameof(record));
|
||||
Utils.CheckArgumentNull(propertyName, nameof(propertyName));
|
||||
|
||||
IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName);
|
||||
if (property != null)
|
||||
{
|
||||
IEdmCollectionExpression collection = property.Value as IEdmCollectionExpression;
|
||||
if (collection != null && collection.Elements != null)
|
||||
{
|
||||
IList<string> items = new List<string>();
|
||||
foreach (var item in collection.Elements)
|
||||
{
|
||||
IEdmStringConstantExpression itemRecord = item as IEdmStringConstantExpression;
|
||||
items.Add(itemRecord.Value);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ using Microsoft.OData.Edm;
|
|||
using Microsoft.OData.Edm.Validation;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Context information for the <see cref="IEdmModel"/>, configuration, etc.
|
||||
/// </summary>
|
||||
internal class ODataContext
|
||||
{
|
||||
private IDictionary<IEdmTypeReference, IEdmOperation> _boundOperations;
|
||||
private bool _keyAsSegmentSupported = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
public ODataContext(IEdmModel model)
|
||||
: this(model, new OpenApiConvertSettings())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="model">The Edm model.</param>
|
||||
/// <param name="settings">The convert setting.</param>
|
||||
public ODataContext(IEdmModel model, OpenApiConvertSettings settings)
|
||||
{
|
||||
Model = model ?? throw Error.ArgumentNull(nameof(model));
|
||||
Settings = settings ?? throw Error.ArgumentNull(nameof(settings));
|
||||
|
||||
EdmModelVisitor visitor = new EdmModelVisitor();
|
||||
visitor.Visit(model);
|
||||
IsSpatialTypeUsed = visitor.IsSpatialTypeUsed;
|
||||
|
||||
_keyAsSegmentSupported = settings.KeyAsSegment ?? model.GetKeyAsSegmentSupported();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm model.
|
||||
/// </summary>
|
||||
public IEdmModel Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Entity Container.
|
||||
/// </summary>
|
||||
public IEdmEntityContainer EntityContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
return Model.EntityContainer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the boolean value indicating to support key as segment.
|
||||
/// </summary>
|
||||
public bool KeyAsSegment => _keyAsSegmentSupported;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value indicating the Edm spatial type used.
|
||||
/// </summary>
|
||||
public bool IsSpatialTypeUsed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the convert settings.
|
||||
/// </summary>
|
||||
public OpenApiConvertSettings Settings { get; }
|
||||
|
||||
public IDictionary<IEdmTypeReference, IEdmOperation> BoundOperations
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_boundOperations == null)
|
||||
{
|
||||
GenerateBoundOperations();
|
||||
}
|
||||
|
||||
return _boundOperations;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IEdmOperation> FindOperations(IEdmEntityType entityType, bool collection)
|
||||
{
|
||||
string fullTypeName = collection ? "Collection(" + entityType.FullName() + ")" :
|
||||
entityType.FullName();
|
||||
|
||||
foreach (var item in BoundOperations)
|
||||
{
|
||||
if (item.Key.FullName() == fullTypeName)
|
||||
{
|
||||
yield return item.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateBoundOperations()
|
||||
{
|
||||
if (_boundOperations != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_boundOperations = new Dictionary<IEdmTypeReference, IEdmOperation>();
|
||||
foreach (var edmOperation in Model.SchemaElements.OfType<IEdmOperation>().Where(e => e.IsBound))
|
||||
{
|
||||
IEdmOperationParameter bindingParameter = edmOperation.Parameters.First();
|
||||
_boundOperations.Add(bindingParameter.Type, edmOperation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@
|
|||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -21,10 +23,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiComponents"/> object.</returns>
|
||||
public static OpenApiComponents CreateComponents(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// "components": {
|
||||
// "schemas": …,
|
||||
|
@ -51,7 +50,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
|
||||
Examples = null,
|
||||
|
||||
SecuritySchemes = null,
|
||||
SecuritySchemes = context.CreateSecuritySchemes(),
|
||||
|
||||
Links = null,
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -20,10 +21,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiDocument"/> object.</returns>
|
||||
public static OpenApiDocument CreateDocument(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// An OAS document consists of a single OpenAPI Object represented as OpenApiDocument object.
|
||||
// {
|
||||
|
@ -34,13 +32,13 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
// "paths": …,
|
||||
// "components": …
|
||||
// }
|
||||
return new OpenApiDocument
|
||||
OpenApiDocument doc = new OpenApiDocument
|
||||
{
|
||||
Info = context.CreateInfo(),
|
||||
|
||||
Servers = context.CreateServers(),
|
||||
|
||||
Tags = context.CreateTags(),
|
||||
// Tags = context.CreateTags(),
|
||||
|
||||
Paths = context.CreatePaths(),
|
||||
|
||||
|
@ -50,6 +48,9 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
|
||||
ExternalDocs = null
|
||||
};
|
||||
|
||||
doc.Tags = context.CreateTags_FromTagItems();
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Exceptions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Properties;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -27,15 +29,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmTypeReference edmTypeReference)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (edmTypeReference == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(edmTypeReference));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(edmTypeReference, nameof(edmTypeReference));
|
||||
|
||||
switch (edmTypeReference.TypeKind())
|
||||
{
|
||||
|
@ -84,15 +79,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveTypeReference primitiveType)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (primitiveType == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(primitiveType));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
|
||||
|
||||
OpenApiSchema schema = context.CreateSchema(primitiveType.PrimitiveDefinition());
|
||||
if (schema != null)
|
||||
|
@ -149,15 +137,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveType primitiveType)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (primitiveType == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(primitiveType));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
|
||||
|
||||
// Spec has different configure for double, AnyOf or OneOf?
|
||||
OpenApiSchema schema = new OpenApiSchema
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -22,10 +24,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The string/schema dictionary.</returns>
|
||||
public static IDictionary<string, OpenApiSchema> CreateODataErrorSchemas(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
IDictionary<string, OpenApiSchema> schemas = new Dictionary<string, OpenApiSchema>();
|
||||
|
||||
|
@ -50,7 +49,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
return new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"error"
|
||||
},
|
||||
|
@ -80,7 +79,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
return new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"code", "message"
|
||||
},
|
||||
|
@ -131,7 +130,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
return new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"code", "message"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Exceptions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to create <see cref="OpenApiExample"/> by <see cref="ODataContext"/>.
|
||||
/// </summary>
|
||||
internal static class OpenApiExampleGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the dictionary of <see cref="OpenApiExample"/> object.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData to Open API context.</param>
|
||||
/// <param name="securitySchemes">The securitySchemes.</param>
|
||||
/// <returns>The created <see cref="OpenApiExample"/> dictionary.</returns>
|
||||
public static IDictionary<string, OpenApiExample> CreateExamples(this ODataContext context)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
IDictionary<string, OpenApiExample> examples = new Dictionary<string, OpenApiExample>();
|
||||
|
||||
// Each entity type, complex type, enumeration type, and type definition directly
|
||||
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
||||
foreach (var element in context.Model.SchemaElements.Where(c => !c.Namespace.StartsWith("Org.OData.")))
|
||||
{
|
||||
switch (element.SchemaElementKind)
|
||||
{
|
||||
case EdmSchemaElementKind.TypeDefinition: // Type definition
|
||||
{
|
||||
IEdmType reference = (IEdmType)element;
|
||||
OpenApiExample example = context.CreateExample(reference);
|
||||
if (example != null)
|
||||
{
|
||||
examples.Add(reference.FullTypeName(), example);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return examples;
|
||||
}
|
||||
|
||||
private static OpenApiExample CreateExample(this ODataContext context, IEdmType edmType)
|
||||
{
|
||||
Debug.Assert(context != null);
|
||||
Debug.Assert(edmType != null);
|
||||
|
||||
switch (edmType.TypeKind)
|
||||
{
|
||||
case EdmTypeKind.Complex: // complex type
|
||||
case EdmTypeKind.Entity: // entity type
|
||||
return CreateStructuredTypeExample((IEdmStructuredType)edmType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static OpenApiExample CreateStructuredTypeExample(IEdmStructuredType structuredType)
|
||||
{
|
||||
OpenApiExample example = new OpenApiExample();
|
||||
|
||||
OpenApiObject value = new OpenApiObject();
|
||||
|
||||
IEdmEntityType entityType = structuredType as IEdmEntityType;
|
||||
|
||||
// properties
|
||||
foreach (var property in structuredType.DeclaredProperties.OrderBy(p => p.Name))
|
||||
{
|
||||
// IOpenApiAny item;
|
||||
IEdmTypeReference propertyType = property.Type;
|
||||
|
||||
IOpenApiAny item = GetTypeNameForExample(propertyType);
|
||||
|
||||
EdmTypeKind typeKind = propertyType.TypeKind();
|
||||
if (typeKind == EdmTypeKind.Primitive && item is OpenApiString)
|
||||
{
|
||||
OpenApiString stringAny = item as OpenApiString;
|
||||
string propertyValue = stringAny.Value;
|
||||
if (entityType != null && entityType.Key().Any(k => k.Name == property.Name))
|
||||
{
|
||||
propertyValue += " (identifier)";
|
||||
}
|
||||
if (propertyType.IsDateTimeOffset() || propertyType.IsDate() || propertyType.IsTimeOfDay())
|
||||
{
|
||||
propertyValue += " (timestamp)";
|
||||
}
|
||||
item = new OpenApiString(propertyValue);
|
||||
}
|
||||
|
||||
value.Add(property.Name, item);
|
||||
}
|
||||
example.Value = value;
|
||||
return example;
|
||||
}
|
||||
|
||||
private static IOpenApiAny GetTypeNameForExample(IEdmTypeReference edmTypeReference)
|
||||
{
|
||||
switch (edmTypeReference.TypeKind())
|
||||
{
|
||||
case EdmTypeKind.Primitive:
|
||||
if (edmTypeReference.IsBoolean())
|
||||
{
|
||||
return new OpenApiBoolean(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OpenApiString(edmTypeReference.AsPrimitive().PrimitiveDefinition().Name);
|
||||
}
|
||||
|
||||
case EdmTypeKind.Entity:
|
||||
case EdmTypeKind.Complex:
|
||||
case EdmTypeKind.Enum:
|
||||
OpenApiObject obj = new OpenApiObject();
|
||||
obj["@odata.type"] = new OpenApiString(edmTypeReference.FullName());
|
||||
return obj;
|
||||
|
||||
case EdmTypeKind.Collection:
|
||||
OpenApiArray array = new OpenApiArray();
|
||||
IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType();
|
||||
array.Add(GetTypeNameForExample(elementType));
|
||||
return array;
|
||||
|
||||
case EdmTypeKind.Untyped:
|
||||
case EdmTypeKind.TypeDefinition:
|
||||
case EdmTypeKind.EntityReference:
|
||||
default:
|
||||
throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -22,10 +24,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiInfo"/> object.</returns>
|
||||
public static OpenApiInfo CreateInfo(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// The value of info is an Info Object,
|
||||
// It contains the fields title and version, and optionally the field description.
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to create <see cref="OpenApiLink"/> by <see cref="IEdmModel"/>.
|
||||
/// </summary>
|
||||
internal static class OpenApiLinkGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the collection of <see cref="OpenApiLink"/> object.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="entitySet">The Entity Set.</param>
|
||||
/// <returns>The created dictionary of <see cref="OpenApiLink"/> object.</returns>
|
||||
public static IDictionary<string, OpenApiLink> CreateLinks(this ODataContext context, IEdmEntitySet entitySet)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
|
||||
|
||||
IDictionary<string, OpenApiLink> links = new Dictionary<string, OpenApiLink>();
|
||||
IEdmEntityType entityType = entitySet.EntityType();
|
||||
foreach (var np in entityType.DeclaredNavigationProperties())
|
||||
{
|
||||
OpenApiLink link = new OpenApiLink();
|
||||
string typeName = entitySet.EntityType().Name;
|
||||
link.OperationId = entitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName);
|
||||
link.Parameters = new Dictionary<string, RuntimeExpressionAnyWrapper>();
|
||||
foreach (var key in entityType.Key())
|
||||
{
|
||||
link.Parameters[key.Name] = new RuntimeExpressionAnyWrapper
|
||||
{
|
||||
Any = new OpenApiString("$request.path." + key.Name)
|
||||
};
|
||||
}
|
||||
|
||||
links[np.Name] = link;
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
|||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Exceptions;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Properties;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ using Microsoft.OpenApi.Models;
|
|||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
using Microsoft.OData.Edm.Vocabularies;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -27,10 +28,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created map of <see cref="OpenApiParameter"/> object.</returns>
|
||||
public static IDictionary<string, OpenApiParameter> CreateParameters(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// It allows defining query options and headers that can be reused across operations of the service.
|
||||
// The value of parameters is a map of Parameter Objects.
|
||||
|
@ -52,15 +50,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created list of <see cref="OpenApiParameter"/>.</returns>
|
||||
public static IList<OpenApiParameter> CreateParameters(this ODataContext context, IEdmFunctionImport functionImport)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (functionImport == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(functionImport));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(functionImport, nameof(functionImport));
|
||||
|
||||
return context.CreateParameters(functionImport.Function);
|
||||
}
|
||||
|
@ -73,15 +64,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created list of <see cref="OpenApiParameter"/>.</returns>
|
||||
public static IList<OpenApiParameter> CreateParameters(this ODataContext context, IEdmFunction function)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (function == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(function));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(function, nameof(function));
|
||||
|
||||
IList<OpenApiParameter> parameters = new List<OpenApiParameter>();
|
||||
int skip = function.IsBound ? 1 : 0;
|
||||
|
@ -134,10 +118,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created the list of <see cref="OpenApiParameter"/>.</returns>
|
||||
public static IList<OpenApiParameter> CreateKeyParameters(this ODataContext context, IEdmEntityType entityType)
|
||||
{
|
||||
if (entityType == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(entityType));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(entityType, nameof(entityType));
|
||||
|
||||
IList<OpenApiParameter> parameters = new List<OpenApiParameter>();
|
||||
|
||||
|
@ -153,6 +135,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
Schema = context.CreateEdmTypeSchema(keyProperty.Type)
|
||||
};
|
||||
|
||||
parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name));
|
||||
|
||||
parameters.Add(parameter);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
// ------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.PathItem;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -33,345 +31,13 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
return pathItems;
|
||||
}
|
||||
|
||||
// visit all elements in the container
|
||||
foreach (var element in context.EntityContainer.Elements)
|
||||
foreach (ODataPath path in context.Paths)
|
||||
{
|
||||
switch (element.ContainerElementKind)
|
||||
{
|
||||
case EdmContainerElementKind.EntitySet: // entity set
|
||||
IEdmEntitySet entitySet = (IEdmEntitySet)element;
|
||||
// entity set
|
||||
string entitySetPathName = "/" + entitySet.Name;
|
||||
var entitySetPathItem = context.CreateEntitySetPathItem(entitySet);
|
||||
pathItems.Add(entitySetPathName, entitySetPathItem);
|
||||
|
||||
// entity
|
||||
string entityPathName = context.CreateEntityPathName(entitySet);
|
||||
var entityPathItem = context.CreateEntityPathItem(entitySet);
|
||||
pathItems.Add(entityPathName, entityPathItem);
|
||||
|
||||
// navigation property
|
||||
foreach (var item in context.CreateNavigationPathItems(entitySet))
|
||||
{
|
||||
pathItems.Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
// bound operations to entity set or entity
|
||||
foreach (var item in context.CreateOperationPathItems(entitySet))
|
||||
{
|
||||
pathItems.Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EdmContainerElementKind.Singleton: // singleton
|
||||
IEdmSingleton singleton = (IEdmSingleton)element;
|
||||
string singletonPathName = "/" + singleton.Name;
|
||||
var singletonPathItem = context.CreateSingletonPathItem(singleton);
|
||||
pathItems.Add(singletonPathName, singletonPathItem);
|
||||
|
||||
// navigation property
|
||||
foreach (var item in context.CreateNavigationPathItems(singleton))
|
||||
{
|
||||
pathItems.Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
// bound operations to singleton
|
||||
foreach (var item in context.CreateOperationPathItems(singleton))
|
||||
{
|
||||
pathItems.Add(item.Key, item.Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case EdmContainerElementKind.FunctionImport: // function import
|
||||
IEdmFunctionImport functionImport = (IEdmFunctionImport)element;
|
||||
string functionImportName = context.CreatePathItemName(functionImport);
|
||||
var functionImportPathItem = context.CreatePathItem(functionImport);
|
||||
pathItems.Add(functionImportName, functionImportPathItem);
|
||||
break;
|
||||
|
||||
case EdmContainerElementKind.ActionImport: // action import
|
||||
IEdmActionImport actionImport = (IEdmActionImport)element;
|
||||
string actionImportName = context.CreatePathItemName(actionImport);
|
||||
var actionImportPathItem = context.CreatePathItem(actionImport);
|
||||
pathItems.Add(actionImportName, actionImportPathItem);
|
||||
break;
|
||||
}
|
||||
IPathItemHandler handler = context.PathItemHanderProvider.GetHandler(path.PathType);
|
||||
pathItems.Add(path.ToString(), handler.CreatePathItem(context, path));
|
||||
}
|
||||
|
||||
return pathItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for <see cref="IEdmEntitySet"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="entitySet">The Edm entity set.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
public static OpenApiPathItem CreateEntitySetPathItem(this ODataContext context, IEdmEntitySet entitySet)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
pathItem.AddOperation(OperationType.Get, context.CreateEntitySetGetOperation(entitySet));
|
||||
|
||||
InsertRestrictions insert = new InsertRestrictions(context.Model, entitySet);
|
||||
if (insert.IsInsertable())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Post, context.CreateEntitySetPostOperation(entitySet));
|
||||
}
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single entity in <see cref="IEdmEntitySet"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="entitySet">The Edm entity set.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
public static OpenApiPathItem CreateEntityPathItem(this ODataContext context, IEdmEntitySet entitySet)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
IndexableByKey index = new IndexableByKey(context.Model, entitySet);
|
||||
if (index.IsSupported())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Get, context.CreateEntityGetOperation(entitySet));
|
||||
}
|
||||
|
||||
UpdateRestrictions update = new UpdateRestrictions(context.Model, entitySet);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Patch, context.CreateEntityPatchOperation(entitySet));
|
||||
}
|
||||
|
||||
DeleteRestrictions delete = new DeleteRestrictions(context.Model, entitySet);
|
||||
if (delete.IsDeletable())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Delete, context.CreateEntityDeleteOperation(entitySet));
|
||||
}
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for <see cref="IEdmSingleton"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="singleton">The singleton.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/> on this singleton.</returns>
|
||||
public static OpenApiPathItem CreateSingletonPathItem(this ODataContext context, IEdmSingleton singleton)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(singleton, nameof(singleton));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
// Retrieve a singleton.
|
||||
pathItem.AddOperation(OperationType.Get, context.CreateSingletonGetOperation(singleton));
|
||||
|
||||
// Update a singleton
|
||||
pathItem.AddOperation(OperationType.Patch, context.CreateSingletonPatchOperation(singleton));
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the bound operations for the navigation source.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="navigationSource">The navigation source.</param>
|
||||
/// <returns>The name/value pairs describing the allowed operations on this navigation source.</returns>
|
||||
public static IDictionary<string, OpenApiPathItem> CreateOperationPathItems(this ODataContext context,
|
||||
IEdmNavigationSource navigationSource)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
|
||||
|
||||
IDictionary<string, OpenApiPathItem> operationPathItems = new Dictionary<string, OpenApiPathItem>();
|
||||
|
||||
IEnumerable<IEdmOperation> operations;
|
||||
IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
|
||||
|
||||
// collection bound
|
||||
if (entitySet != null)
|
||||
{
|
||||
operations = context.FindOperations(navigationSource.EntityType(), collection: true);
|
||||
foreach (var operation in operations)
|
||||
{
|
||||
OpenApiPathItem pathItem = context.CreatePathItem(navigationSource, operation);
|
||||
string pathName = context.CreatePathItemName(operation);
|
||||
operationPathItems.Add("/" + navigationSource.Name + pathName, pathItem);
|
||||
}
|
||||
}
|
||||
|
||||
// non-collection bound
|
||||
operations = context.FindOperations(navigationSource.EntityType(), collection: false);
|
||||
foreach (var operation in operations)
|
||||
{
|
||||
OpenApiPathItem pathItem = context.CreatePathItem(navigationSource, operation);
|
||||
string pathName = context.CreatePathItemName(operation);
|
||||
|
||||
string entityPathName;
|
||||
if (entitySet != null)
|
||||
{
|
||||
entityPathName = context.CreateEntityPathName(entitySet);
|
||||
|
||||
OpenApiOperation openApiOperation = pathItem.Operations.First().Value;
|
||||
Debug.Assert(openApiOperation != null);
|
||||
openApiOperation.Parameters = context.CreateKeyParameters(entitySet.EntityType());
|
||||
}
|
||||
else
|
||||
{
|
||||
entityPathName = "/" + navigationSource.Name;
|
||||
}
|
||||
|
||||
operationPathItems.Add(entityPathName + pathName, pathItem);
|
||||
}
|
||||
|
||||
return operationPathItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the navigation property path item for the navigation source.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="navigationSource">The navigation source.</param>
|
||||
/// <returns>The name/value pairs describing the allowed operations on this navigation source.</returns>
|
||||
public static IDictionary<string, OpenApiPathItem> CreateNavigationPathItems(this ODataContext context,
|
||||
IEdmNavigationSource navigationSource)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
|
||||
|
||||
IDictionary<string, OpenApiPathItem> navPathItems = new Dictionary<string, OpenApiPathItem>();
|
||||
if (!context.Settings.NavigationPropertyPathItem)
|
||||
{
|
||||
return navPathItems;
|
||||
}
|
||||
|
||||
IEdmEntityType entityType = navigationSource.EntityType();
|
||||
foreach (var navProperty in entityType.DeclaredNavigationProperties())
|
||||
{
|
||||
string pathItemName = context.CreateNavigationPathItemName(navigationSource, navProperty);
|
||||
OpenApiPathItem pathItem = context.CreatePathItem(navigationSource, navProperty);
|
||||
|
||||
navPathItems.Add(pathItemName, pathItem);
|
||||
}
|
||||
|
||||
return navPathItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single <see cref="IEdmNavigationProperty"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="navigationSource">The binding navigation source.</param>
|
||||
/// <param name="navigationProperty">The Edm navigation property.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
public static OpenApiPathItem CreatePathItem(this ODataContext context, IEdmNavigationSource navigationSource,
|
||||
IEdmNavigationProperty navigationProperty)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
|
||||
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
pathItem.AddOperation(OperationType.Get, context.CreateNavigationGetOperation(navigationSource, navigationProperty));
|
||||
|
||||
if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
InsertRestrictions insert = new InsertRestrictions(context.Model, navigationProperty);
|
||||
if (insert.IsInsertable())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Post, context.CreateNavigationPostOperation(navigationSource, navigationProperty));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateRestrictions update = new UpdateRestrictions(context.Model, navigationProperty);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
pathItem.AddOperation(OperationType.Patch, context.CreateNavigationPatchOperation(navigationSource, navigationProperty));
|
||||
}
|
||||
}
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single <see cref="IEdmOperation"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="navigationSource">The binding navigation source.</param>
|
||||
/// <param name="edmOperation">The Edm opeation.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
public static OpenApiPathItem CreatePathItem(this ODataContext context, IEdmNavigationSource navigationSource, IEdmOperation edmOperation)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
|
||||
Utils.CheckArgumentNull(edmOperation, nameof(edmOperation));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
OpenApiOperation operation = context.CreateOperation(navigationSource, edmOperation);
|
||||
|
||||
if (edmOperation.IsAction())
|
||||
{
|
||||
// The Path Item Object for a bound action contains the keyword post,
|
||||
// The value of the operation keyword is an Operation Object that describes how to invoke the action.
|
||||
pathItem.AddOperation(OperationType.Post, operation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The Path Item Object for a bound function contains the keyword get,
|
||||
// The value of the operation keyword is an Operation Object that describes how to invoke the function.
|
||||
pathItem.AddOperation(OperationType.Get, operation);
|
||||
}
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single <see cref="IEdmOperationImport"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="operationImport">The Edm operation import.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
public static OpenApiPathItem CreatePathItem(this ODataContext context, IEdmOperationImport operationImport)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(operationImport, nameof(operationImport));
|
||||
|
||||
OpenApiPathItem pathItem = new OpenApiPathItem();
|
||||
|
||||
OpenApiOperation operation = context.CreateOperation(operationImport);
|
||||
|
||||
if (operationImport.IsActionImport())
|
||||
{
|
||||
// Each action import is represented as a name/value pair whose name is the service-relative
|
||||
// resource path of the action import prepended with a forward slash, and whose value is a Path
|
||||
// Item Object containing the keyword post with an Operation Object as value that describes
|
||||
// how to invoke the action import.
|
||||
pathItem.AddOperation(OperationType.Post, operation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Each function import is represented as a name/value pair whose name is the service-relative
|
||||
// resource path of the function import prepended with a forward slash, and whose value is a Path
|
||||
// Item Object containing the keyword get with an Operation Object as value that describes
|
||||
// how to invoke the function import.
|
||||
pathItem.AddOperation(OperationType.Get, operation);
|
||||
}
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -23,10 +25,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiPaths"/> object.</returns>
|
||||
public static OpenApiPaths CreatePaths(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// Due to the power and flexibility of OData a full representation of all service capabilities
|
||||
// in the Paths Object is typically not feasible, so this mapping only describes the minimum
|
||||
|
|
|
@ -7,6 +7,8 @@ using System.Linq;
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -23,15 +25,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiRequestBody"/> or null.</returns>
|
||||
public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmActionImport actionImport)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (actionImport == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(actionImport));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(actionImport, nameof(actionImport));
|
||||
|
||||
return context.CreateRequestBody(actionImport.Action);
|
||||
}
|
||||
|
@ -44,15 +39,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiRequestBody"/> or null.</returns>
|
||||
public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmAction action)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (action == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(action));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(action, nameof(action));
|
||||
|
||||
// return null for empty action parameters
|
||||
int skip = 0;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -57,10 +59,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The name/value pairs for the standard OData error response.</returns>
|
||||
public static IDictionary<string, OpenApiResponse> CreateResponses(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
return new Dictionary<string, OpenApiResponse>
|
||||
{
|
||||
|
@ -76,15 +75,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiResponses"/>.</returns>
|
||||
public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperationImport operationImport)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (operationImport == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(operationImport));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(operationImport, nameof(operationImport));
|
||||
|
||||
return context.CreateResponses(operationImport.Operation);
|
||||
}
|
||||
|
@ -97,15 +89,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiResponses"/>.</returns>
|
||||
public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (operation == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(operation));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(operation, nameof(operation));
|
||||
|
||||
OpenApiResponses responses = new OpenApiResponses();
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ using Microsoft.OData.Edm;
|
|||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.OData.Properties;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.Exceptions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -27,16 +31,13 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The string/schema dictionary.</returns>
|
||||
public static IDictionary<string, OpenApiSchema> CreateSchemas(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
IDictionary<string, OpenApiSchema> schemas = new Dictionary<string, OpenApiSchema>();
|
||||
|
||||
// Each entity type, complex type, enumeration type, and type definition directly
|
||||
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
||||
foreach (var element in context.Model.SchemaElements)
|
||||
foreach (var element in context.Model.SchemaElements.Where(c => !c.Namespace.StartsWith("Org.OData.")))
|
||||
{
|
||||
switch (element.SchemaElementKind)
|
||||
{
|
||||
|
@ -74,15 +75,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdmEnumType enumType)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (enumType == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(enumType));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(enumType, nameof(enumType));
|
||||
|
||||
OpenApiSchema schema = new OpenApiSchema
|
||||
{
|
||||
|
@ -115,17 +109,10 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
|
||||
|
||||
if (structuredType == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(structuredType));
|
||||
}
|
||||
|
||||
return context.CreateStructuredTypeSchema(structuredType, true);
|
||||
return context.CreateStructuredTypeSchema(structuredType, true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -139,15 +126,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created <see cref="OpenApiSchema"/>.</returns>
|
||||
public static OpenApiSchema CreatePropertySchema(this ODataContext context, IEdmProperty property)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (property == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(property));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(property, nameof(property));
|
||||
|
||||
OpenApiSchema schema = context.CreateEdmTypeSchema(property.Type);
|
||||
|
||||
|
@ -174,6 +154,9 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created map of <see cref="OpenApiSchema"/>.</returns>
|
||||
public static IDictionary<string, OpenApiSchema> CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
|
||||
|
||||
// The name is the property name, the value is a Schema Object describing the allowed values of the property.
|
||||
IDictionary<string, OpenApiSchema> properties = new Dictionary<string, OpenApiSchema>();
|
||||
|
||||
|
@ -209,7 +192,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
{
|
||||
case EdmTypeKind.Complex: // complex type
|
||||
case EdmTypeKind.Entity: // entity type
|
||||
return context.CreateStructuredTypeSchema((IEdmStructuredType)edmType, true);
|
||||
return context.CreateStructuredTypeSchema((IEdmStructuredType)edmType, true, true);
|
||||
|
||||
case EdmTypeKind.Enum: // enum type
|
||||
return context.CreateEnumTypeSchema((IEdmEnumType)edmType);
|
||||
|
@ -223,7 +206,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
|
||||
private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType, bool processBase)
|
||||
private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType, bool processBase, bool processExample)
|
||||
{
|
||||
Debug.Assert(context != null);
|
||||
Debug.Assert(structuredType != null);
|
||||
|
@ -247,12 +230,13 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
},
|
||||
|
||||
// 2. a Schema Object describing the derived type
|
||||
context.CreateStructuredTypeSchema(structuredType, false)
|
||||
context.CreateStructuredTypeSchema(structuredType, false, false)
|
||||
},
|
||||
|
||||
AnyOf = null,
|
||||
OneOf = null,
|
||||
Properties = null
|
||||
Properties = null,
|
||||
Example = CreateStructuredTypePropertiesExample(structuredType)
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -287,10 +271,86 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
schema.Description = context.Model.GetDescriptionAnnotation(entity);
|
||||
}
|
||||
|
||||
if (processExample)
|
||||
{
|
||||
schema.Example = CreateStructuredTypePropertiesExample(structuredType);
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
|
||||
private static IOpenApiAny CreateStructuredTypePropertiesExample(IEdmStructuredType structuredType)
|
||||
{
|
||||
OpenApiObject example = new OpenApiObject();
|
||||
|
||||
IEdmEntityType entityType = structuredType as IEdmEntityType;
|
||||
|
||||
// properties
|
||||
foreach (var property in structuredType.Properties())
|
||||
{
|
||||
// IOpenApiAny item;
|
||||
IEdmTypeReference propertyType = property.Type;
|
||||
|
||||
IOpenApiAny item = GetTypeNameForExample(propertyType);
|
||||
|
||||
EdmTypeKind typeKind = propertyType.TypeKind();
|
||||
if (typeKind == EdmTypeKind.Primitive && item is OpenApiString)
|
||||
{
|
||||
OpenApiString stringAny = item as OpenApiString;
|
||||
string value = stringAny.Value;
|
||||
if (entityType != null && entityType.Key().Any(k => k.Name == property.Name))
|
||||
{
|
||||
value += " (identifier)";
|
||||
}
|
||||
if (propertyType.IsDateTimeOffset() || propertyType.IsDate() || propertyType.IsTimeOfDay())
|
||||
{
|
||||
value += " (timestamp)";
|
||||
}
|
||||
item = new OpenApiString(value);
|
||||
}
|
||||
|
||||
example.Add(property.Name, item);
|
||||
}
|
||||
|
||||
return example;
|
||||
}
|
||||
|
||||
private static IOpenApiAny GetTypeNameForExample(IEdmTypeReference edmTypeReference)
|
||||
{
|
||||
switch (edmTypeReference.TypeKind())
|
||||
{
|
||||
case EdmTypeKind.Primitive:
|
||||
if (edmTypeReference.IsBoolean())
|
||||
{
|
||||
return new OpenApiBoolean(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OpenApiString(edmTypeReference.AsPrimitive().PrimitiveDefinition().Name);
|
||||
}
|
||||
|
||||
case EdmTypeKind.Entity:
|
||||
case EdmTypeKind.Complex:
|
||||
case EdmTypeKind.Enum:
|
||||
OpenApiObject obj = new OpenApiObject();
|
||||
obj["@odata.type"] = new OpenApiString(edmTypeReference.FullName());
|
||||
return obj;
|
||||
|
||||
case EdmTypeKind.Collection:
|
||||
OpenApiArray array = new OpenApiArray();
|
||||
IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType();
|
||||
array.Add(GetTypeNameForExample(elementType));
|
||||
return array;
|
||||
|
||||
case EdmTypeKind.Untyped:
|
||||
case EdmTypeKind.TypeDefinition:
|
||||
case EdmTypeKind.EntityReference:
|
||||
default:
|
||||
throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind());
|
||||
}
|
||||
}
|
||||
|
||||
private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
|
||||
{
|
||||
if (property == null ||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Authorizations;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to create <see cref="OpenApiSecurityRequirement"/> by <see cref="ODataContext"/>.
|
||||
/// </summary>
|
||||
internal static class OpenApiSecurityRequirementGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the list of <see cref="OpenApiSecurityRequirement"/> object.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData to Open API context.</param>
|
||||
/// <param name="securitySchemes">The securitySchemes.</param>
|
||||
/// <returns>The created <see cref="OpenApiSecurityRequirement"/> collection.</returns>
|
||||
public static IEnumerable<OpenApiSecurityRequirement> CreateSecurityRequirements(this ODataContext context,
|
||||
IList<SecurityScheme> securitySchemes)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
if (securitySchemes != null)
|
||||
{
|
||||
foreach (var securityScheme in securitySchemes)
|
||||
{
|
||||
yield return new OpenApiSecurityRequirement
|
||||
{
|
||||
[
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = securityScheme.AuthorizationSchemeName
|
||||
}
|
||||
}
|
||||
] = new List<string>(securityScheme.RequiredScopes ?? new List<string>())
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Authorizations;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods to create <see cref="OpenApiSecurityScheme"/> by <see cref="ODataContext"/>.
|
||||
/// </summary>
|
||||
internal static class OpenApiSecuritySchemeGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the dictionary of <see cref="OpenApiSecurityScheme"/> object.
|
||||
/// The name of each pair is the name of authorization. The value of each pair is a <see cref="OpenApiSecurityScheme"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData to Open API context.</param>
|
||||
/// <returns>The string/security scheme dictionary.</returns>
|
||||
public static IDictionary<string, OpenApiSecurityScheme> CreateSecuritySchemes(this ODataContext context)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
if (context.Model == null || context.Model.EntityContainer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IDictionary<string, OpenApiSecurityScheme> securitySchemes = new Dictionary<string, OpenApiSecurityScheme>();
|
||||
var authorizations = context.AuthorizationProvider.GetAuthorizations(context.Model, context.EntityContainer);
|
||||
foreach (var authorization in authorizations)
|
||||
{
|
||||
OpenApiSecurityScheme scheme = new OpenApiSecurityScheme
|
||||
{
|
||||
Type = authorization.SchemeType,
|
||||
Description = authorization.Description
|
||||
};
|
||||
|
||||
switch (authorization.SchemeType)
|
||||
{
|
||||
case SecuritySchemeType.ApiKey: // ApiKey
|
||||
AppendApiKey(scheme, (ApiKey)authorization);
|
||||
break;
|
||||
|
||||
case SecuritySchemeType.Http: // Http
|
||||
AppendHttp(scheme, (Http)authorization);
|
||||
break;
|
||||
|
||||
case SecuritySchemeType.OpenIdConnect: // OpenIdConnect
|
||||
AppendOpenIdConnect(scheme, (OpenIDConnect)authorization);
|
||||
break;
|
||||
|
||||
case SecuritySchemeType.OAuth2: // OAuth2
|
||||
AppendOAuth2(scheme, (OAuthAuthorization)authorization);
|
||||
break;
|
||||
}
|
||||
|
||||
securitySchemes[authorization.Name] = scheme;
|
||||
}
|
||||
|
||||
return securitySchemes;
|
||||
}
|
||||
|
||||
private static void AppendApiKey(OpenApiSecurityScheme scheme, ApiKey apiKey)
|
||||
{
|
||||
Debug.Assert(scheme != null);
|
||||
Debug.Assert(apiKey != null);
|
||||
|
||||
scheme.Name = apiKey.KeyName;
|
||||
|
||||
Debug.Assert(apiKey.Location != null);
|
||||
switch(apiKey.Location.Value)
|
||||
{
|
||||
case KeyLocation.Cookie:
|
||||
scheme.In = ParameterLocation.Cookie;
|
||||
break;
|
||||
|
||||
case KeyLocation.Header:
|
||||
scheme.In = ParameterLocation.Header;
|
||||
break;
|
||||
|
||||
case KeyLocation.QueryOption:
|
||||
scheme.In = ParameterLocation.Query;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendHttp(OpenApiSecurityScheme scheme, Http http)
|
||||
{
|
||||
Debug.Assert(scheme != null);
|
||||
Debug.Assert(http != null);
|
||||
|
||||
scheme.Scheme = http.Scheme;
|
||||
scheme.BearerFormat = http.BearerFormat;
|
||||
}
|
||||
|
||||
private static void AppendOpenIdConnect(OpenApiSecurityScheme scheme, OpenIDConnect openIdConnect)
|
||||
{
|
||||
Debug.Assert(scheme != null);
|
||||
Debug.Assert(openIdConnect != null);
|
||||
|
||||
scheme.OpenIdConnectUrl = new Uri(openIdConnect.IssuerUrl);
|
||||
}
|
||||
|
||||
private static void AppendOAuth2(OpenApiSecurityScheme scheme, OAuthAuthorization oAuth2)
|
||||
{
|
||||
Debug.Assert(scheme != null);
|
||||
Debug.Assert(oAuth2 != null);
|
||||
|
||||
scheme.Flows = new OpenApiOAuthFlows();
|
||||
OpenApiOAuthFlow flow = null;
|
||||
switch (oAuth2.OAuth2Type)
|
||||
{
|
||||
case OAuth2Type.AuthCode: // AuthCode
|
||||
OAuth2AuthCode authCode = (OAuth2AuthCode)oAuth2;
|
||||
flow = new OpenApiOAuthFlow
|
||||
{
|
||||
AuthorizationUrl = new Uri(authCode.AuthorizationUrl),
|
||||
TokenUrl = new Uri(authCode.TokenUrl)
|
||||
};
|
||||
scheme.Flows.AuthorizationCode = flow;
|
||||
break;
|
||||
|
||||
case OAuth2Type.Pasword: // Password
|
||||
OAuth2Password password = (OAuth2Password)oAuth2;
|
||||
flow = new OpenApiOAuthFlow
|
||||
{
|
||||
TokenUrl = new Uri(password.TokenUrl)
|
||||
};
|
||||
scheme.Flows.Password = flow;
|
||||
break;
|
||||
|
||||
case OAuth2Type.Implicit: // Implicit
|
||||
OAuth2Implicit @implicit = (OAuth2Implicit)oAuth2;
|
||||
flow = new OpenApiOAuthFlow
|
||||
{
|
||||
AuthorizationUrl = new Uri(@implicit.AuthorizationUrl)
|
||||
};
|
||||
scheme.Flows.Implicit = flow;
|
||||
break;
|
||||
|
||||
case OAuth2Type.ClientCredentials: // ClientCredentials
|
||||
OAuth2ClientCredentials credentials = (OAuth2ClientCredentials)oAuth2;
|
||||
flow = new OpenApiOAuthFlow
|
||||
{
|
||||
TokenUrl = new Uri(credentials.TokenUrl)
|
||||
};
|
||||
scheme.Flows.ClientCredentials = flow;
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.Assert(flow != null);
|
||||
flow.RefreshUrl = new Uri(oAuth2.RefreshUrl);
|
||||
|
||||
if (oAuth2.Scopes != null)
|
||||
{
|
||||
flow.Scopes = oAuth2.Scopes.ToDictionary(s => s.Scope, s => s.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -20,10 +22,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created collection of <see cref="OpenApiServer"/> object.</returns>
|
||||
public static IList<OpenApiServer> CreateServers(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// The value of servers is an array of Server Objects.
|
||||
// It contains one object with a field url.
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -23,10 +25,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The string/schema dictionary.</returns>
|
||||
public static IDictionary<string, OpenApiSchema> CreateSpatialSchemas(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
IDictionary<string, OpenApiSchema> schemas = new Dictionary<string, OpenApiSchema>();
|
||||
|
||||
|
@ -243,7 +242,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
},
|
||||
{ "coordinates", new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" } } }
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -278,7 +277,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -317,7 +316,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -351,7 +350,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -390,7 +389,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -433,7 +432,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
@ -467,7 +466,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
}
|
||||
}
|
||||
},
|
||||
Required = new List<string>
|
||||
Required = new HashSet<string>
|
||||
{
|
||||
"type",
|
||||
"coordinates"
|
||||
|
|
|
@ -7,6 +7,8 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -15,6 +17,12 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// </summary>
|
||||
internal static class OpenApiTagGenerator
|
||||
{
|
||||
public static IList<OpenApiTag> CreateTags_FromTagItems(this ODataContext context)
|
||||
{
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
return context.Tags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the collection of <see cref="OpenApiTag"/> object.
|
||||
/// </summary>
|
||||
|
@ -22,10 +30,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created collection of <see cref="OpenApiTag"/> object.</returns>
|
||||
public static IList<OpenApiTag> CreateTags(this ODataContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
|
||||
// The value of tags is an array of Tag Objects.
|
||||
// For an OData service the natural groups are entity sets and singletons,
|
||||
|
|
|
@ -9,6 +9,8 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Generator
|
||||
{
|
||||
|
@ -25,15 +27,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created path item name.</returns>
|
||||
public static string CreateEntityPathName(this ODataContext context, IEdmEntitySet entitySet)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (entitySet == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(entitySet));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(entitySet, nameof(entitySet));
|
||||
|
||||
StringBuilder sb = new StringBuilder("/" + entitySet.Name);
|
||||
IList<IEdmStructuralProperty> keys = entitySet.EntityType().Key().ToList();
|
||||
|
@ -69,15 +64,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// <returns>The created path item name</returns>
|
||||
public static string CreatePathItemName(this ODataContext context, IEdmOperationImport operationImport)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (operationImport == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(operationImport));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(operationImport, nameof(operationImport));
|
||||
|
||||
if (operationImport.IsActionImport())
|
||||
{
|
||||
|
@ -86,9 +74,19 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
else
|
||||
{
|
||||
StringBuilder functionName = new StringBuilder("/" + operationImport.Name + "(");
|
||||
|
||||
functionName.Append(String.Join(",",
|
||||
operationImport.Operation.Parameters.Select(p => p.Name + "=" + "{" + p.Name + "}")));
|
||||
operationImport.Operation.Parameters.Select(p =>
|
||||
{
|
||||
if (p.Type.IsStructured() || p.Type.IsCollection())
|
||||
{
|
||||
return p.Name + "=@" + p.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return p.Name + "={" + p.Name + "}";
|
||||
}
|
||||
})));
|
||||
|
||||
functionName.Append(")");
|
||||
|
||||
return functionName.ToString();
|
||||
|
@ -99,19 +97,12 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
/// Create the path item name for a <see cref="IEdmOperation"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The OData context.</param>
|
||||
/// <param name="function">The Edm function.</param>
|
||||
/// <param name="operation">The Edm operation.</param>
|
||||
/// <returns>The created path item name</returns>
|
||||
public static string CreatePathItemName(this ODataContext context, IEdmOperation operation)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (operation == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(operation));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(operation, nameof(operation));
|
||||
|
||||
if (operation.IsAction())
|
||||
{
|
||||
|
@ -131,20 +122,9 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
public static string CreateNavigationPathItemName(this ODataContext context,
|
||||
IEdmNavigationSource navigationSource, IEdmNavigationProperty navigationProperty)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(context));
|
||||
}
|
||||
|
||||
if (navigationSource == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(navigationSource));
|
||||
}
|
||||
|
||||
if (navigationProperty == null)
|
||||
{
|
||||
throw Error.ArgumentNull(nameof(navigationProperty));
|
||||
}
|
||||
Utils.CheckArgumentNull(context, nameof(context));
|
||||
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
|
||||
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
|
||||
|
||||
string pathItemName;
|
||||
IEdmEntitySet entitySet = navigationSource as IEdmEntitySet;
|
||||
|
@ -179,30 +159,17 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
// Structured or collection-valued parameters are represented as a parameter alias in the path template
|
||||
// and the parameters array contains a Parameter Object for the parameter alias as a query option of type string.
|
||||
int skip = function.IsBound ? 1 : 0;
|
||||
int index = 0;
|
||||
int parameterAliasIndex = 1;
|
||||
foreach (IEdmOperationParameter edmParameter in function.Parameters.Skip(skip))
|
||||
functionName.Append(String.Join(",", function.Parameters.Skip(skip).Select(p =>
|
||||
{
|
||||
if (index == 0)
|
||||
if (p.Type.IsStructured() || p.Type.IsCollection())
|
||||
{
|
||||
index++;
|
||||
return p.Name + "=@" + p.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
functionName.Append(",");
|
||||
}
|
||||
|
||||
if (edmParameter.Type.IsStructured() ||
|
||||
edmParameter.Type.IsCollection())
|
||||
{
|
||||
functionName.Append(edmParameter.Name).Append("=")
|
||||
.Append(context.Settings.ParameterAlias).Append(parameterAliasIndex++);
|
||||
}
|
||||
else
|
||||
{
|
||||
functionName.Append(edmParameter.Name).Append("={").Append(edmParameter.Name).Append("}");
|
||||
}
|
||||
return p.Name + "={" + p.Name + "}";
|
||||
}
|
||||
})));
|
||||
|
||||
functionName.Append(")");
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.OData.Edm" Version="7.3.1" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.0.0-beta012" />
|
||||
<PackageReference Include="Microsoft.OData.Edm" Version="7.5.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using Microsoft.OpenApi.OData.Abstractions;
|
||||
|
||||
namespace Microsoft.OpenApi.OData
|
||||
{
|
||||
|
@ -42,10 +43,35 @@ namespace Microsoft.OpenApi.OData
|
|||
/// </summary>
|
||||
public bool EnumPrefixFree { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating whether to output the path for Edm operation.
|
||||
/// </summary>
|
||||
public bool EnableOperationPath { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating whether to output the path for Edm operation import.
|
||||
/// </summary>
|
||||
public bool EnableOperationImportPath { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating whether to output the path for Edm navigation property.
|
||||
/// </summary>
|
||||
public bool EnableNavigationPropertyPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating the navigation property depth.
|
||||
/// </summary>
|
||||
public bool NavigationPropertyPathItem { get; set; }
|
||||
public int NavigationPropertyDepth { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating the tags name depth.
|
||||
/// </summary>
|
||||
public int TagDepth { get; set; } = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating whether we count key segment as a depth.
|
||||
/// </summary>
|
||||
public bool CountKeySegmentAsDepth { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/set a value indicating the prefix for the parameter alias.
|
||||
|
@ -68,5 +94,7 @@ namespace Microsoft.OpenApi.OData
|
|||
/// otherwise keep number without quotes.
|
||||
/// </summary>
|
||||
public bool IEEE754Compatible { get; set; }
|
||||
|
||||
public IAuthorizationProvider AuthorizationProvider { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// The Open Api operation for <see cref="IEdmActionImport"/>.
|
||||
/// </summary>
|
||||
internal class EdmActionImportOperationHandler : EdmOperationImportOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Post;
|
||||
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
IEdmActionImport actionImport = EdmOperationImport as IEdmActionImport;
|
||||
|
||||
// The requestBody field contains a Request Body Object describing the structure of the request body.
|
||||
// Its schema value follows the rules for Schema Objects for complex types, with one property per action parameter.
|
||||
operation.RequestBody = Context.CreateRequestBody(actionImport);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("actionImport"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// The Open Api operation for <see cref="IEdmAction"/>.
|
||||
/// </summary>
|
||||
internal class EdmActionOperationHandler : EdmOperationOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Post;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm Action.
|
||||
/// </summary>
|
||||
public IEdmAction Action => EdmOperation as IEdmAction;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
IEdmAction action = EdmOperation as IEdmAction;
|
||||
if (action != null)
|
||||
{
|
||||
operation.RequestBody = Context.CreateRequestBody(action);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("action"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// The Open Api operation for <see cref="IEdmFunctionImport"/>.
|
||||
/// </summary>
|
||||
internal class EdmFunctionImportOperationHandler : EdmOperationImportOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
IEdmFunctionImport functionImport = EdmOperationImport as IEdmFunctionImport;
|
||||
//The parameters array contains a Parameter Object for each parameter of the function overload,
|
||||
// and it contains specific Parameter Objects for the allowed system query options.
|
||||
operation.Parameters = Context.CreateParameters(functionImport);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("functionImport"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// The Open Api operation for <see cref="IEdmFunction"/>.
|
||||
/// </summary>
|
||||
internal class EdmFunctionOperationHandler : EdmOperationOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm Function.
|
||||
/// </summary>
|
||||
public IEdmFunction Function => EdmOperation as IEdmFunction;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("function"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
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>
|
||||
/// Base class for <see cref="IEdmOperationImport"/>.
|
||||
/// </summary>
|
||||
internal abstract class EdmOperationImportOperationHandler : OperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IEdmOperationImport"/>.
|
||||
/// </summary>
|
||||
protected IEdmOperationImport EdmOperationImport { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataOperationImportSegment operationImportSegment = path.LastSegment as ODataOperationImportSegment;
|
||||
EdmOperationImport = operationImportSegment.OperationImport;
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
operation.Summary = "Invoke " + (EdmOperationImport.IsActionImport() ? "action " : "function ") + EdmOperationImport.Name;
|
||||
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string key = "OperationImport." + EdmOperationImport.Name;
|
||||
operation.OperationId += "OperationImport." + Context.GetIndex(key) + "-" + Utils.UpperFirstChar(EdmOperationImport.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
// The responses object contains a name/value pair for the success case (HTTP response code 200)
|
||||
// describing the structure of the success response by referencing an appropriate schema
|
||||
// in the global schemas. In addition, it contains a default name/value pair for
|
||||
// the OData error response referencing the global responses.
|
||||
operation.Responses = Context.CreateResponses(EdmOperationImport);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
operation.Tags = CreateTags(EdmOperationImport);
|
||||
operation.Tags[0].Extensions.Add(Constants.xMsTocType, new OpenApiString("container"));
|
||||
Context.AppendTag(operation.Tags[0]);
|
||||
}
|
||||
|
||||
private static IList<OpenApiTag> CreateTags(IEdmOperationImport operationImport)
|
||||
{
|
||||
if (operationImport.EntitySet != null)
|
||||
{
|
||||
var pathExpression = operationImport.EntitySet as IEdmPathExpression;
|
||||
if (pathExpression != null)
|
||||
{
|
||||
return new List<OpenApiTag>
|
||||
{
|
||||
new OpenApiTag
|
||||
{
|
||||
Name = PathAsString(pathExpression.PathSegments)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return new List<OpenApiTag>{
|
||||
new OpenApiTag
|
||||
{
|
||||
Name = operationImport.Name
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal static string PathAsString(IEnumerable<string> path)
|
||||
{
|
||||
return String.Join("/", path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
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>
|
||||
/// Base class for operation of <see cref="IEdmOperation"/>.
|
||||
/// </summary>
|
||||
internal abstract class EdmOperationOperationHandler : OperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the navigation source.
|
||||
/// </summary>
|
||||
protected IEdmNavigationSource NavigationSource { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Edm operation.
|
||||
/// </summary>
|
||||
protected IEdmOperation EdmOperation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the path has type cast segment or not.
|
||||
/// </summary>
|
||||
protected bool HasTypeCast { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
NavigationSource = navigationSourceSegment.NavigationSource;
|
||||
|
||||
ODataOperationSegment operationSegment = path.LastSegment as ODataOperationSegment;
|
||||
EdmOperation = operationSegment.Operation;
|
||||
|
||||
HasTypeCast = path.Segments.Any(s => s is ODataTypeCastSegment);
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Invoke " + (EdmOperation.IsAction() ? "action " : "function ") + EdmOperation.Name;
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string key = NavigationSource.Name + "-" + Utils.UpperFirstChar(EdmOperation.Name);
|
||||
int index = Context.GetIndex(key);
|
||||
operation.OperationId = NavigationSource.Name + "." + index + "-" + Utils.UpperFirstChar(EdmOperation.Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
string value = EdmOperation.IsAction() ? "Actions" : "Functions";
|
||||
OpenApiTag tag = new OpenApiTag
|
||||
{
|
||||
Name = NavigationSource.Name + "." + value,
|
||||
};
|
||||
tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("container"));
|
||||
operation.Tags.Add(tag);
|
||||
|
||||
Context.AppendTag(tag);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
/*
|
||||
IEdmSingleton singleton = NavigationSource as IEdmSingleton;
|
||||
if (singleton == null && EdmOperation.IsBound)
|
||||
{
|
||||
IEdmOperationParameter bindingParameter = EdmOperation.Parameters.FirstOrDefault();
|
||||
if (bindingParameter != null &&
|
||||
!bindingParameter.Type.IsCollection() && // bound to a single entity
|
||||
bindingParameter.Type.IsEntity())
|
||||
{
|
||||
operation.Parameters = Context.CreateKeyParameters(bindingParameter
|
||||
.Type.AsEntity().EntityDefinition());
|
||||
}
|
||||
}*/
|
||||
|
||||
if (EdmOperation.IsFunction())
|
||||
{
|
||||
IEdmFunction function = (IEdmFunction)EdmOperation;
|
||||
IList<OpenApiParameter> parameters = Context.CreateParameters(function);
|
||||
if (operation.Parameters == null)
|
||||
{
|
||||
operation.Parameters = parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var parameter in parameters)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = Context.CreateResponses(EdmOperation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Delete an Entity
|
||||
/// The Path Item Object for the entity set contains the keyword delete with an Operation Object as value
|
||||
/// that describes the capabilities for deleting the entity.
|
||||
/// </summary>
|
||||
internal class EntityDeleteOperationHandler : EntitySetOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Delete;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Delete entity from " + EntitySet.Name;
|
||||
// override the summary using the request.Description.
|
||||
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = EntitySet.EntityType().Name;
|
||||
operation.OperationId = EntitySet.Name + "." + typeName + ".Delete" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
operation.Parameters.Add(new OpenApiParameter
|
||||
{
|
||||
Name = "If-Match",
|
||||
In = ParameterLocation.Header,
|
||||
Description = "ETag",
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = "string"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{ Constants.StatusCode204, Constants.StatusCode204.GetResponse() },
|
||||
{ Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse() }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve an Entity:
|
||||
/// The Path Item Object for the entity contains the keyword get with an Operation Object as value
|
||||
/// that describes the capabilities for retrieving a single entity.
|
||||
/// </summary>
|
||||
internal class EntityGetOperationHandler : EntitySetOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Get entity from " + EntitySet.Name + " by key";
|
||||
|
||||
// override the summary using the request.Description.
|
||||
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = EntitySet.EntityType().Name;
|
||||
operation.OperationId = EntitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
// $select
|
||||
OpenApiParameter parameter = Context.CreateSelect(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $expand
|
||||
parameter = Context.CreateExpand(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
|
||||
AppendCustomParameters(operation, request);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved entity",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = EntitySet.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Links = Context.CreateLinks(EntitySet)
|
||||
}
|
||||
}
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetSecurity(OpenApiOperation operation)
|
||||
{
|
||||
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
|
||||
if (request != null)
|
||||
{
|
||||
operation.Security = Context.CreateSecurityRequirements(request.SecuritySchemes).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Update an Entity
|
||||
/// The Path Item Object for the entity set contains the keyword patch with an Operation Object as value
|
||||
/// that describes the capabilities for updating the entity.
|
||||
/// </summary>
|
||||
internal class EntityPatchOperationHandler : EntitySetOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Patch;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Update entity in " + EntitySet.Name;
|
||||
// override the summary using the request.Description.
|
||||
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = EntitySet.EntityType().Name;
|
||||
operation.OperationId = EntitySet.Name + "." + typeName + ".Update" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Description = "New property values",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType, new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = EntitySet.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{ Constants.StatusCode204, Constants.StatusCode204.GetResponse() },
|
||||
{ Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse() }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Query a Collection of Entities, it's a "Get" operation for <see cref="IEdmEntitySet"/>
|
||||
/// The Path Item Object for the entity set contains the keyword get with an Operation Object as value
|
||||
/// that describes the capabilities for querying the entity set.
|
||||
/// For example: "/users"
|
||||
/// </summary>
|
||||
internal class EntitySetGetOperationHandler : EntitySetOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Get entities from " + EntitySet.Name;
|
||||
var request = Context.FindRequest(EntitySet, OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = EntitySet.EntityType().Name;
|
||||
operation.OperationId = EntitySet.Name + "." + typeName + ".List" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
// The parameters array contains Parameter Objects for all system query options allowed for this collection,
|
||||
// and it does not list system query options not allowed for this collection, see terms
|
||||
// Capabilities.TopSupported, Capabilities.SkipSupported, Capabilities.SearchRestrictions,
|
||||
// Capabilities.FilterRestrictions, and Capabilities.CountRestrictions
|
||||
// $top
|
||||
OpenApiParameter parameter = Context.CreateTop(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $skip
|
||||
parameter = Context.CreateSkip(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $search
|
||||
parameter = Context.CreateSearch(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $filter
|
||||
parameter = Context.CreateFilter(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $count
|
||||
parameter = Context.CreateCount(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// the syntax of the system query options $expand, $select, and $orderby is too flexible
|
||||
// to be formally described with OpenAPI Specification means, yet the typical use cases
|
||||
// of just providing a comma-separated list of properties can be expressed via an array-valued
|
||||
// parameter with an enum constraint
|
||||
// $order
|
||||
parameter = Context.CreateOrderBy(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $select
|
||||
parameter = Context.CreateSelect(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $expand
|
||||
parameter = Context.CreateExpand(EntitySet);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
var request = Context.FindRequest(EntitySet, OperationType.ToString());
|
||||
AppendCustomParameters(operation, request);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved entities",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Title = "Collection of " + EntitySet.EntityType().Name,
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{
|
||||
"value",
|
||||
new OpenApiSchema
|
||||
{
|
||||
Type = "array",
|
||||
Items = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = EntitySet.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for entity set operation.
|
||||
/// </summary>
|
||||
internal abstract class EntitySetOperationHandler : OperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets/sets the <see cref="IEdmEntitySet"/>.
|
||||
/// </summary>
|
||||
protected IEdmEntitySet EntitySet { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
// get the entity set.
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet;
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiTag tag = new OpenApiTag
|
||||
{
|
||||
Name = EntitySet.Name + "." + EntitySet.EntityType().Name,
|
||||
};
|
||||
tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
|
||||
operation.Tags.Add(tag);
|
||||
|
||||
Context.AppendTag(tag);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an Entity:
|
||||
/// The Path Item Object for the entity set contains the keyword "post" with an Operation Object as value
|
||||
/// that describes the capabilities for creating new entities.
|
||||
/// </summary>
|
||||
internal class EntitySetPostOperationHandler : EntitySetOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Post;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Add new entity to " + EntitySet.Name;
|
||||
var request = Context.FindRequest(EntitySet, OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = EntitySet.EntityType().Name;
|
||||
operation.OperationId = EntitySet.Name + "." + typeName + ".Create" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
var request = Context.FindRequest(EntitySet, OperationType.ToString());
|
||||
AppendCustomParameters(operation, request);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
// The requestBody field contains a Request Body Object for the request body
|
||||
// that references the schema of the entity set’s entity type in the global schemas.
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Description = "New entity",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType, new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = EntitySet.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode201,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Created entity",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = EntitySet.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to create a <see cref="OpenApiOperation"/> based on <see cref="ODataPath"/>.
|
||||
/// </summary>
|
||||
internal interface IOperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation type.
|
||||
/// </summary>
|
||||
OperationType OperationType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create the <see cref="OpenApiOperation"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="path">The OData path.</param>
|
||||
/// <returns>The created <see cref="OpenApiOperation"/>.</returns>
|
||||
OpenApiOperation CreateOperation(ODataContext context, ODataPath path);
|
||||
}
|
||||
}
|
|
@ -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 Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to provider <see cref="IOperationHandler"/>.
|
||||
/// </summary>
|
||||
internal interface IOperationHandlerProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the <see cref="IOperationHandler"/>.
|
||||
/// </summary>
|
||||
/// <param name="pathType">The path type.</param>
|
||||
/// <param name="operationType">The operation type.</param>
|
||||
/// <returns>The corresponding <see cref="IOperationHandler"/>.</returns>
|
||||
IOperationHandler GetHandler(ODataPathType pathType, OperationType operationType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve a navigation property from a navigation source.
|
||||
/// The Path Item Object for the entity contains the keyword get with an Operation Object as value
|
||||
/// that describes the capabilities for retrieving a navigation property form a navigation source.
|
||||
/// </summary>
|
||||
internal class NavigationPropertyGetOperationHandler : NavigationPropertyOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Get " + NavigationProperty.Name + " from " + NavigationSource.Name;
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string prefix = "Get";
|
||||
if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
prefix = "List";
|
||||
}
|
||||
|
||||
/*
|
||||
string key = NavigationSource.Name + "." + NavigationProperty.Name + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
int index = Context.GetIndex(key);
|
||||
operation.OperationId = NavigationSource.Name + "." + NavigationProperty.Name + index + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
*/
|
||||
operation.OperationId = GetOperationId(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved navigation property",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = NavigationProperty.ToEntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
if (operation.Parameters == null)
|
||||
{
|
||||
operation.Parameters = new List<OpenApiParameter>();
|
||||
}
|
||||
|
||||
if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
// The parameters array contains Parameter Objects for system query options allowed for this entity set,
|
||||
// and it does not list system query options not allowed for this entity set.
|
||||
OpenApiParameter parameter = Context.CreateTop(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSkip(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSearch(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateFilter(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateCount(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateOrderBy(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateSelect(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateExpand(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenApiParameter parameter = Context.CreateSelect(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
parameter = Context.CreateExpand(NavigationProperty);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for operation of <see cref="IEdmNavigationProperty"/>.
|
||||
/// </summary>
|
||||
internal abstract class NavigationPropertyOperationHandler : OperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the navigation property.
|
||||
/// </summary>
|
||||
protected IEdmNavigationProperty NavigationProperty { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the navigation source.
|
||||
/// </summary>
|
||||
protected IEdmNavigationSource NavigationSource { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a bool value indicating whether the last segment is a key segment.
|
||||
/// </summary>
|
||||
protected bool LastSegmentIsKeySegment { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
NavigationSource = navigationSourceSegment.NavigationSource;
|
||||
|
||||
LastSegmentIsKeySegment = path.LastSegment is ODataKeySegment;
|
||||
|
||||
ODataNavigationPropertySegment npSegment = path.LastSegment as ODataNavigationPropertySegment;
|
||||
if (npSegment == null)
|
||||
{
|
||||
npSegment = path.Segments[path.Count - 2] as ODataNavigationPropertySegment;
|
||||
}
|
||||
NavigationProperty = npSegment.NavigationProperty;
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
IList<string> items = new List<string>
|
||||
{
|
||||
NavigationSource.Name
|
||||
};
|
||||
|
||||
foreach (var segment in Path.Segments.Skip(1))
|
||||
{
|
||||
if (segment is ODataNavigationPropertySegment)
|
||||
{
|
||||
ODataNavigationPropertySegment npSegment = (ODataNavigationPropertySegment)segment;
|
||||
if (npSegment.NavigationProperty == NavigationProperty)
|
||||
{
|
||||
items.Add(NavigationProperty.ToEntityType().Name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items.Count >= Context.Settings.TagDepth - 1)
|
||||
{
|
||||
items.Add(npSegment.NavigationProperty.ToEntityType().Name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(segment.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string name = string.Join(".", items);
|
||||
OpenApiTag tag = new OpenApiTag
|
||||
{
|
||||
// Name = NavigationSource.Name + "." + NavigationProperty.ToEntityType().Name,
|
||||
Name = name
|
||||
};
|
||||
tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
|
||||
operation.Tags.Add(tag);
|
||||
|
||||
Context.AppendTag(tag);
|
||||
}
|
||||
|
||||
protected string GetOperationId(string prefix)
|
||||
{
|
||||
IList<string> items = new List<string>
|
||||
{
|
||||
NavigationSource.Name
|
||||
};
|
||||
|
||||
var lastpath = Path.Segments.Last(c => c is ODataNavigationPropertySegment);
|
||||
foreach (var segment in Path.Segments.Skip(1))
|
||||
{
|
||||
if (segment is ODataNavigationPropertySegment)
|
||||
{
|
||||
ODataNavigationPropertySegment npSegment = (ODataNavigationPropertySegment)segment;/*
|
||||
if (npSegment.NavigationProperty == NavigationProperty)
|
||||
{
|
||||
items.Add(prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(segment.Name);
|
||||
}*/
|
||||
if (segment == lastpath)
|
||||
{
|
||||
items.Add(prefix + Utils.UpperFirstChar(segment.Name));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(segment.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join(".", items);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Update a navigation property for a navigation source.
|
||||
/// The Path Item Object for the entity set contains the keyword patch with an Operation Object as value
|
||||
/// that describes the capabilities for updating the navigation property for a navigation source.
|
||||
/// </summary>
|
||||
internal class NavigationPropertyPatchOperationHandler : NavigationPropertyOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Patch;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Update the navigation property " + NavigationProperty.Name + " in " + NavigationSource.Name;
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string prefix = "Update";
|
||||
//string key = NavigationSource.Name + "." + NavigationProperty.Name + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
// int index = Context.GetIndex(key);
|
||||
// operation.OperationId = NavigationSource.Name + "." + NavigationProperty.Name + index + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
|
||||
operation.OperationId = GetOperationId(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Description = "New navigation property values",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType, new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = NavigationProperty.ToEntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{ Constants.StatusCode204, Constants.StatusCode204.GetResponse() },
|
||||
{ Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse() }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a navigation for a navigation source.
|
||||
/// The Path Item Object for the entity set contains the keyword delete with an Operation Object as value
|
||||
/// that describes the capabilities for create a navigation for a navigation source.
|
||||
/// </summary>
|
||||
internal class NavigationPropertyPostOperationHandler : NavigationPropertyOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Post;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Create new navigation property to " + NavigationProperty.Name + " for " + NavigationSource.Name;
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string prefix = "Create";
|
||||
/*
|
||||
string key = NavigationSource.Name + "." + NavigationProperty.Name + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
int index = Context.GetIndex(key);
|
||||
operation.OperationId = NavigationSource.Name + "." + NavigationProperty.Name + index + "-" + prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
|
||||
*/
|
||||
operation.OperationId = GetOperationId(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Description = "New navigation property",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType, new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = NavigationProperty.ToEntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode201,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Created navigation property.",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = NavigationProperty.ToEntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
}
|
||||
}
|
212
src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
Normal file
212
src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
Normal file
|
@ -0,0 +1,212 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Annotations;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for <see cref="OpenApiOperation"/> handler.
|
||||
/// </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.
|
||||
/// </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.EntityType))
|
||||
{
|
||||
operation.Parameters.Add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Tags information for <see cref="OpenApiOperation"/>.
|
||||
/// </summary>
|
||||
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
|
||||
protected virtual void SetTags(OpenApiOperation operation)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Set the Extensions information for <see cref="OpenApiOperation"/>.
|
||||
/// </summary>
|
||||
/// <param name="operation">The <see cref="OpenApiOperation"/>.</param>
|
||||
protected virtual void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("operation"));
|
||||
}
|
||||
|
||||
protected static void AppendCustomParameters(OpenApiOperation operation, HttpRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation.Parameters == null)
|
||||
{
|
||||
operation.Parameters = new List<OpenApiParameter>();
|
||||
}
|
||||
|
||||
if (request.CustomQueryOptions != null)
|
||||
{
|
||||
AppendCustomParameters(operation.Parameters, request.CustomQueryOptions, ParameterLocation.Query);
|
||||
}
|
||||
|
||||
if (request.CustomQueryOptions != null)
|
||||
{
|
||||
AppendCustomParameters(operation.Parameters, request.CustomHeaders, ParameterLocation.Header);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AppendCustomParameters(IList<OpenApiParameter> parameters, IList<CustomParameter> headers, ParameterLocation location)
|
||||
{
|
||||
foreach (var param in headers)
|
||||
{
|
||||
OpenApiParameter parameter = new OpenApiParameter
|
||||
{
|
||||
In = location,
|
||||
Name = param.Name,
|
||||
Description = param.Description,
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
// Type = param.Type
|
||||
},
|
||||
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
|
||||
};
|
||||
|
||||
if (example is ExternalExample)
|
||||
{
|
||||
var externalExample = (ExternalExample)example;
|
||||
ex.Value = new OpenApiString(externalExample.ExternalValue ?? "N/A");
|
||||
}
|
||||
else
|
||||
{
|
||||
var inlineExample = (InlineExample)example;
|
||||
ex.Value = new OpenApiString(inlineExample.InlineValue ?? "N/A");
|
||||
}
|
||||
|
||||
parameter.Examples.Add("example-" + index++, ex);
|
||||
}
|
||||
}
|
||||
|
||||
parameters.Add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to provide the <see cref="IOperationHandler"/>.
|
||||
/// </summary>
|
||||
internal class OperationHandlerProvider : IOperationHandlerProvider
|
||||
{
|
||||
private IDictionary<ODataPathType, IDictionary<OperationType, IOperationHandler>> _handlers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="OperationHandlerProvider"/> class.
|
||||
/// </summary>
|
||||
public OperationHandlerProvider()
|
||||
{
|
||||
_handlers = new Dictionary<ODataPathType, IDictionary<OperationType, IOperationHandler>>();
|
||||
|
||||
// entity set (Get/Post)
|
||||
_handlers[ODataPathType.EntitySet] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new EntitySetGetOperationHandler() },
|
||||
{OperationType.Post, new EntitySetPostOperationHandler() }
|
||||
};
|
||||
|
||||
// entity (Get/Patch/Delete)
|
||||
_handlers[ODataPathType.Entity] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new EntityGetOperationHandler() },
|
||||
{OperationType.Patch, new EntityPatchOperationHandler() },
|
||||
{OperationType.Delete, new EntityDeleteOperationHandler() }
|
||||
};
|
||||
|
||||
// singleton (Get/Patch)
|
||||
_handlers[ODataPathType.Singleton] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new SingletonGetOperationHandler() },
|
||||
{OperationType.Patch, new SingletonPatchOperationHandler() }
|
||||
};
|
||||
|
||||
// edm operation (Get|Post)
|
||||
_handlers[ODataPathType.Operation] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new EdmFunctionOperationHandler() },
|
||||
{OperationType.Post, new EdmActionOperationHandler() }
|
||||
};
|
||||
|
||||
// edm operation import (Get|Post)
|
||||
_handlers[ODataPathType.OperationImport] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new EdmFunctionImportOperationHandler() },
|
||||
{OperationType.Post, new EdmActionImportOperationHandler() }
|
||||
};
|
||||
|
||||
// navigation property (Get/Patch/Post)
|
||||
_handlers[ODataPathType.NavigationProperty] = new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new NavigationPropertyGetOperationHandler() },
|
||||
{OperationType.Patch, new NavigationPropertyPatchOperationHandler() },
|
||||
{OperationType.Post, new NavigationPropertyPostOperationHandler() }
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IOperationHandler GetHandler(ODataPathType pathType, OperationType operationType)
|
||||
{
|
||||
return _handlers[pathType][operationType];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve a Singleton
|
||||
/// The Path Item Object for the entity set contains the keyword get with an Operation Object as value
|
||||
/// that describes the capabilities for retrieving the singleton.
|
||||
/// </summary>
|
||||
internal class SingletonGetOperationHandler : SingletonOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Get " + Singleton.Name;
|
||||
var request = Context.FindRequest(Singleton, OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = Singleton.EntityType().Name;
|
||||
operation.OperationId = Singleton.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
operation.Parameters = new List<OpenApiParameter>();
|
||||
IEdmEntityType entityType = Singleton.EntityType();
|
||||
|
||||
// $select
|
||||
OpenApiParameter parameter = Context.CreateSelect(Singleton);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
// $expand
|
||||
parameter = Context.CreateExpand(Singleton);
|
||||
if (parameter != null)
|
||||
{
|
||||
operation.Parameters.Add(parameter);
|
||||
}
|
||||
|
||||
var request = Context.FindRequest(Singleton, OperationType.ToString());
|
||||
AppendCustomParameters(operation, request);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved entity",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = Singleton.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for operation of <see cref="IEdmSingleton"/>.
|
||||
/// </summary>
|
||||
internal abstract class SingletonOperationHandler : OperationHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IEdmSingleton"/>.
|
||||
/// </summary>
|
||||
protected IEdmSingleton Singleton { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
|
||||
Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton;
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiTag tag = new OpenApiTag
|
||||
{
|
||||
Name = Singleton.Name + "." + Singleton.EntityType().Name,
|
||||
};
|
||||
tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
|
||||
operation.Tags.Add(tag);
|
||||
|
||||
Context.AppendTag(tag);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Generator;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation
|
||||
{
|
||||
/// <summary>
|
||||
/// Update a Singleton
|
||||
/// The Path Item Object for the entity set contains the keyword patch with an Operation Object as value
|
||||
/// that describes the capabilities for updating the singleton, unless the singleton is read-only.
|
||||
/// </summary>
|
||||
internal class SingletonPatchOperationHandler : SingletonOperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Patch;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
operation.Summary = "Update " + Singleton.Name;
|
||||
var request = Context.FindRequest(Singleton, OperationType.ToString());
|
||||
if (request != null && request.Description != null)
|
||||
{
|
||||
operation.Summary = request.Description;
|
||||
}
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.OperationId)
|
||||
{
|
||||
string typeName = Singleton.EntityType().Name;
|
||||
operation.OperationId = Singleton.Name + "." + typeName + ".Update" + Utils.UpperFirstChar(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetRequestBody(OpenApiOperation operation)
|
||||
{
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Description = "New property values",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType, new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = Singleton.EntityType().FullName()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{ Constants.StatusCode204, Constants.StatusCode204.GetResponse() },
|
||||
{ Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse() }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Capabilities;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Path item handler for Entity Set.
|
||||
/// </summary>
|
||||
internal class EntityPathItemHandler : EntitySetPathItemHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
IndexableByKey index = new IndexableByKey(Context.Model, EntitySet);
|
||||
if (index.IsSupported())
|
||||
{
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
|
||||
UpdateRestrictions update = new UpdateRestrictions(Context.Model, EntitySet);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
AddOperation(item, OperationType.Patch);
|
||||
}
|
||||
|
||||
DeleteRestrictions delete = new DeleteRestrictions(Context.Model, EntitySet);
|
||||
if (delete.IsDeletable())
|
||||
{
|
||||
AddOperation(item, OperationType.Delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for <see cref="IEdmEntitySet"/>.
|
||||
/// </summary>
|
||||
internal class EntitySetPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entity set.
|
||||
/// </summary>
|
||||
protected IEdmEntitySet EntitySet { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
AddOperation(item, OperationType.Get);
|
||||
|
||||
InsertRestrictions insert = new InsertRestrictions(Context.Model, EntitySet);
|
||||
if (insert.IsInsertable())
|
||||
{
|
||||
AddOperation(item, OperationType.Post);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet;
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for <see cref="OpenApiPathItem"/>.
|
||||
/// </summary>
|
||||
internal interface IPathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Create <see cref="OpenApiPathItem"/> based on <see cref="ODataContext"/> and <see cref="ODataPath"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns>The created <see cref="OpenApiPathItem"/>.</returns>
|
||||
OpenApiPathItem CreatePathItem(ODataContext context, ODataPath path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for <see cref="IPathItemHandler"/>.
|
||||
/// </summary>
|
||||
internal interface IPathItemHandlerProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the <see cref="IPathItemHandler"/> based on the path type.
|
||||
/// </summary>
|
||||
/// <param name="pathType">The path type.</param>
|
||||
/// <returns>The <see cref="IPathItemHandler"/>.</returns>
|
||||
IPathItemHandler GetHandler(ODataPathType pathType);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single <see cref="IEdmNavigationProperty"/>.
|
||||
/// </summary>
|
||||
internal class NavigationPropertyPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the navigation property.
|
||||
/// </summary>
|
||||
public IEdmNavigationProperty NavigationProperty { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the navigation source.
|
||||
/// </summary>
|
||||
public IEdmNavigationSource NavigationSource { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a bool value indicating whether the last segment is a key segment.
|
||||
/// </summary>
|
||||
protected bool LastSegmentIsKeySegment { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
// contaiment: Get / (Post - Collection | Patch - Single)
|
||||
// non-containment: only Get
|
||||
AddOperation(item, OperationType.Get);
|
||||
|
||||
if (NavigationProperty.ContainsTarget)
|
||||
{
|
||||
if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
if (LastSegmentIsKeySegment)
|
||||
{
|
||||
UpdateRestrictions update = new UpdateRestrictions(Context.Model, NavigationProperty);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
AddOperation(item, OperationType.Patch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertRestrictions insert = new InsertRestrictions(Context.Model, NavigationProperty);
|
||||
if (insert.IsInsertable())
|
||||
{
|
||||
AddOperation(item, OperationType.Post);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateRestrictions update = new UpdateRestrictions(Context.Model, NavigationProperty);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
AddOperation(item, OperationType.Patch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
NavigationSource = navigationSourceSegment.NavigationSource;
|
||||
|
||||
LastSegmentIsKeySegment = path.LastSegment is ODataKeySegment;
|
||||
ODataNavigationPropertySegment npSegment = path.LastSegment as ODataNavigationPropertySegment;
|
||||
if (npSegment == null)
|
||||
{
|
||||
npSegment = path.Segments[path.Count - 2] as ODataNavigationPropertySegment;
|
||||
}
|
||||
NavigationProperty = npSegment.NavigationProperty;
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiPathItem item)
|
||||
{
|
||||
IList<ODataPath> samePaths = new List<ODataPath>();
|
||||
foreach (var path in Context.Paths.Where(p => p.PathType == ODataPathType.NavigationProperty && p != Path))
|
||||
{
|
||||
bool lastIsKeySegment = path.LastSegment is ODataKeySegment;
|
||||
if (LastSegmentIsKeySegment != lastIsKeySegment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
if (NavigationSource != navigationSourceSegment.NavigationSource)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ODataNavigationPropertySegment npSegment = path.LastSegment as ODataNavigationPropertySegment;
|
||||
if (npSegment == null)
|
||||
{
|
||||
npSegment = path.Segments[path.Count - 2] as ODataNavigationPropertySegment;
|
||||
}
|
||||
if (NavigationProperty != npSegment.NavigationProperty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
samePaths.Add(path);
|
||||
}
|
||||
|
||||
if (samePaths.Any())
|
||||
{
|
||||
OpenApiArray array = new OpenApiArray();
|
||||
foreach(var p in samePaths)
|
||||
{
|
||||
array.Add(new OpenApiString(p.ToString()));
|
||||
}
|
||||
|
||||
item.Extensions.Add(Constants.xMsDosGroupPath, array);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for a single <see cref="IEdmOperationImport"/>.
|
||||
/// </summary>
|
||||
internal class OperationImportPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the operation import.
|
||||
/// </summary>
|
||||
public IEdmOperationImport EdmOperationImport { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
if (EdmOperationImport.IsActionImport())
|
||||
{
|
||||
// Each action import is represented as a name/value pair whose name is the service-relative
|
||||
// resource path of the action import prepended with a forward slash, and whose value is a Path
|
||||
// Item Object containing the keyword post with an Operation Object as value that describes
|
||||
// how to invoke the action import.
|
||||
AddOperation(item, OperationType.Post);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Each function import is represented as a name/value pair whose name is the service-relative
|
||||
// resource path of the function import prepended with a forward slash, and whose value is a Path
|
||||
// Item Object containing the keyword get with an Operation Object as value that describes
|
||||
// how to invoke the function import.
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataOperationImportSegment operationImportSegment = path.FirstSegment as ODataOperationImportSegment;
|
||||
EdmOperationImport = operationImportSegment.OperationImport;
|
||||
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the bound operations for the navigation source.
|
||||
/// </summary>
|
||||
internal class OperationPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Edm operation.
|
||||
/// </summary>
|
||||
public IEdmOperation EdmOperation { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
if (EdmOperation.IsAction())
|
||||
{
|
||||
// The Path Item Object for a bound action contains the keyword post,
|
||||
// The value of the operation keyword is an Operation Object that describes how to invoke the action.
|
||||
AddOperation(item, OperationType.Post);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The Path Item Object for a bound function contains the keyword get,
|
||||
// The value of the operation keyword is an Operation Object that describes how to invoke the function.
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataOperationSegment operationSegment = path.LastSegment as ODataOperationSegment;
|
||||
EdmOperation = operationSegment.Operation;
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetExtensions(OpenApiPathItem item)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = Path.FirstSegment as ODataNavigationSourceSegment;
|
||||
IEdmNavigationSource currentNavSource = navigationSourceSegment.NavigationSource;
|
||||
|
||||
IList<ODataPath> samePaths = new List<ODataPath>();
|
||||
foreach (var path in Context.Paths.Where(p => p.PathType == ODataPathType.Operation && p != Path))
|
||||
{
|
||||
navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
if (currentNavSource != navigationSourceSegment.NavigationSource)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ODataOperationSegment operationSegment = path.LastSegment as ODataOperationSegment;
|
||||
if (EdmOperation.FullName() != operationSegment.Operation.FullName())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
samePaths.Add(path);
|
||||
}
|
||||
|
||||
if (samePaths.Any())
|
||||
{
|
||||
OpenApiArray array = new OpenApiArray();
|
||||
foreach (var p in samePaths)
|
||||
{
|
||||
array.Add(new OpenApiString(p.ToString()));
|
||||
}
|
||||
|
||||
item.Extensions.Add(Constants.xMsDosGroupPath, array);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.Common;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.Operation;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for <see cref="IPathItemHandler"/>.
|
||||
/// </summary>
|
||||
internal abstract class PathItemHandler : IPathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the OData Context.
|
||||
/// </summary>
|
||||
protected ODataContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the OData Path.
|
||||
/// </summary>
|
||||
protected ODataPath Path { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual OpenApiPathItem CreatePathItem(ODataContext context, ODataPath path)
|
||||
{
|
||||
Context = context ?? throw Error.ArgumentNull(nameof(context));
|
||||
|
||||
Path = path ?? throw Error.ArgumentNull(nameof(path));
|
||||
|
||||
Initialize(context, path);
|
||||
|
||||
OpenApiPathItem item = new OpenApiPathItem();
|
||||
|
||||
SetOperations(item);
|
||||
|
||||
SetExtensions(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the operation for the path item.
|
||||
/// </summary>
|
||||
/// <param name="item">The path item.</param>
|
||||
protected abstract void SetOperations(OpenApiPathItem item);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Handler.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="path">The path.</param>
|
||||
protected virtual void Initialize(ODataContext context, ODataPath path)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Set the extensions for the path item.
|
||||
/// </summary>
|
||||
/// <param name="item">The path item.</param>
|
||||
protected virtual void SetExtensions(OpenApiPathItem item)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Add one operation into path item.
|
||||
/// </summary>
|
||||
/// <param name="item">The path item.</param>
|
||||
/// <param name="operationType">The operatin type.</param>
|
||||
protected void AddOperation(OpenApiPathItem item, OperationType operationType)
|
||||
{
|
||||
IOperationHandlerProvider provider = Context.OperationHanderProvider;
|
||||
IOperationHandler operationHander = provider.GetHandler(Path.PathType, operationType);
|
||||
item.AddOperation(operationType, operationHander.CreateOperation(Context, Path));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// ------------------------------------------------------------
|
||||
// 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.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Default path item handler provider.
|
||||
/// </summary>
|
||||
internal class PathItemHandlerProvider : IPathItemHandlerProvider
|
||||
{
|
||||
private IDictionary<ODataPathType, IPathItemHandler> _handlers = new Dictionary<ODataPathType, IPathItemHandler>
|
||||
{
|
||||
// Entity
|
||||
{ ODataPathType.EntitySet, new EntitySetPathItemHandler() },
|
||||
|
||||
// Entity
|
||||
{ ODataPathType.Entity, new EntityPathItemHandler() },
|
||||
|
||||
// Singleton
|
||||
{ ODataPathType.Singleton, new SingletonPathItemHandler() },
|
||||
|
||||
// Navigation property
|
||||
{ ODataPathType.NavigationProperty, new NavigationPropertyPathItemHandler() },
|
||||
|
||||
// Edm Operation
|
||||
{ ODataPathType.Operation, new OperationPathItemHandler() },
|
||||
|
||||
// Edm OperationImport
|
||||
{ ODataPathType.OperationImport, new OperationImportPathItemHandler() },
|
||||
};
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPathItemHandler GetHandler(ODataPathType pathType)
|
||||
{
|
||||
return _handlers[pathType];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Capabilities;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a <see cref="OpenApiPathItem"/> for <see cref="IEdmSingleton"/>.
|
||||
/// </summary>
|
||||
internal class SingletonPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entity set.
|
||||
/// </summary>
|
||||
protected IEdmSingleton Singleton { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
// Retrieve a singleton.
|
||||
AddOperation(item, OperationType.Get);
|
||||
|
||||
// Update a singleton
|
||||
UpdateRestrictions update = new UpdateRestrictions(Context.Model, Singleton);
|
||||
if (update.IsUpdatable())
|
||||
{
|
||||
AddOperation(item, OperationType.Patch);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
|
||||
Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton;
|
||||
base.Initialize(context, path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,6 +69,15 @@ namespace Microsoft.OpenApi.OData.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The authorization record type name '{0}' is not correct..
|
||||
/// </summary>
|
||||
internal static string AuthorizationRecordTypeNameNotCorrect {
|
||||
get {
|
||||
return ResourceManager.GetString("AuthorizationRecordTypeNameNotCorrect", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The filed name of extension doesn't begin with x-..
|
||||
/// </summary>
|
||||
|
|
|
@ -120,6 +120,9 @@
|
|||
<data name="ArgumentNullOrEmpty" xml:space="preserve">
|
||||
<value>The argument '{0}' is null or empty.</value>
|
||||
</data>
|
||||
<data name="AuthorizationRecordTypeNameNotCorrect" xml:space="preserve">
|
||||
<value>The authorization record type name '{0}' is not correct.</value>
|
||||
</data>
|
||||
<data name="ExtensionFieldNameMustBeginWithXMinus" xml:space="preserve">
|
||||
<value>The filed name of extension doesn't begin with x-.</value>
|
||||
</data>
|
||||
|
|
|
@ -254,7 +254,7 @@ namespace OoasGui
|
|||
|
||||
private void NavPathcheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Settings.NavigationPropertyPathItem = !Settings.NavigationPropertyPathItem;
|
||||
Settings.EnableNavigationPropertyPath = !Settings.EnableNavigationPropertyPath;
|
||||
Convert();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.OData.Edm, Version=7.3.1.10814, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.OData.Edm.7.3.1\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll</HintPath>
|
||||
<Reference Include="Microsoft.OData.Edm, Version=7.5.0.20627, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.OData.Edm.7.5.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.OpenApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3f5743946376f042, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.OpenApi.1.0.0-beta012\lib\net46\Microsoft.OpenApi.dll</HintPath>
|
||||
<Reference Include="Microsoft.OpenApi, Version=1.0.1.0, Culture=neutral, PublicKeyToken=3f5743946376f042, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.OpenApi.1.0.1\lib\net46\Microsoft.OpenApi.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.OData.Edm" version="7.3.1" targetFramework="net461" />
|
||||
<package id="Microsoft.OpenApi" version="1.0.0-beta012" targetFramework="net461" />
|
||||
<package id="Microsoft.OData.Edm" version="7.5.0" targetFramework="net461" />
|
||||
<package id="Microsoft.OpenApi" version="1.0.1" targetFramework="net461" />
|
||||
</packages>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue