modify the HttpRequest annotation and add test cases

This commit is contained in:
Sam Xu 2018-09-11 10:58:32 -07:00
parent 97ff1aaf1d
commit 8495c737b7
30 changed files with 137739 additions and 87447 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,129 @@
// ------------------------------------------------------------
// 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 provider
/// </summary>
internal class HttpRequestProvider
{
/// <summary>
/// Annotatable: EntitySet Singleton ActionImport FunctionImport Action Function
/// Collection(Core.HttpRequest)
/// </summary>
private IDictionary<IEdmVocabularyAnnotatable, IList<HttpRequest>> _requests
= new Dictionary<IEdmVocabularyAnnotatable, IList<HttpRequest>>();
/// <summary>
/// Gets the Edm mode.
/// </summary>
public IEdmModel Model { get; }
/// <summary>
/// Gets the Edm Term.
/// </summary>
public IEdmTerm Term { get; }
/// <summary>
/// Initializes a new instance of <see cref="HttpRequestProvider"/> class.
/// </summary>
/// <param name="model">The Edm model.</param>
public HttpRequestProvider(IEdmModel model)
{
Utils.CheckArgumentNull(model, nameof(model));
Term = model.FindTerm("Org.OData.Core.V1.HttpRequests");
Model = model;
}
/// <summary>
/// Gets Org.OData.Core.V1.HttpRequest.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="method">The request method.</param>
/// <returns>The Org.OData.Core.V1.HttpRequest or null.</returns>
public HttpRequest GetHttpRequest(IEdmVocabularyAnnotatable target, string method)
{
Utils.CheckArgumentNull(target, nameof(target));
Utils.CheckArgumentNull(method, nameof(method));
var requests = GetHttpRequests(target);
return requests?.FirstOrDefault(e => string.Equals(e.MethodType, method, System.StringComparison.OrdinalIgnoreCase));
}
/// <summary>
/// Gets the collection of Org.OData.Core.V1.HttpRequest for a given <see cref="IEdmVocabularyAnnotatable"/>.
/// </summary>
/// <param name="target">The target.</param>
/// <returns>The collection of Org.OData.Core.V1.HttpRequest</returns>
public IEnumerable<HttpRequest> GetHttpRequests(IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(target, nameof(target));
if (Term == null)
{
return null;
}
// Search the cache.
if (_requests.TryGetValue(target, out IList<HttpRequest> value))
{
return value;
}
IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(target, Term);
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, Term);
}
}
if (annotation == null ||
annotation.Value == null ||
annotation.Value.ExpressionKind != EdmExpressionKind.Collection)
{
_requests[target] = null;
return null;
}
if (target is IEdmEntitySet)
{
IEdmEntitySet entitySet = target as IEdmEntitySet;
if (entitySet.Name == "domains")
{
int pp = 0;
}
}
IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value;
var httpRequests = new List<HttpRequest>();
foreach (var item in collection.Elements)
{
IEdmRecordExpression record = (IEdmRecordExpression)item;
HttpRequest newRequest = new HttpRequest();
newRequest.Init(record);
httpRequests.Add(newRequest);
}
_requests[target] = httpRequests;
return httpRequests;
}
}
}

View file

@ -1,100 +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.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);
}
}
}
}

View file

@ -1,154 +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.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

View file

@ -29,6 +29,7 @@ namespace Microsoft.OpenApi.OData.Edm
private bool _keyAsSegmentSupported = false;
private IList<OpenApiTag> _tags = new List<OpenApiTag>();
private ODataPathHandler _pathHandler;
public HttpRequestProvider _httpRequestProvider;
/// <summary>
/// Initializes a new instance of <see cref="ODataContext"/> class.
@ -53,13 +54,13 @@ namespace Microsoft.OpenApi.OData.Edm
visitor.Visit(model);
IsSpatialTypeUsed = visitor.IsSpatialTypeUsed;
_pathHandler = new ODataPathHandler(this);
OperationHanderProvider = new OperationHandlerProvider();
PathItemHanderProvider = new PathItemHandlerProvider();
AuthorizationProvider = new AuthorizationProvider();
_httpRequestProvider = new HttpRequestProvider(model);
if (settings.EnableKeyAsSegment != null)
{
@ -89,8 +90,6 @@ namespace Microsoft.OpenApi.OData.Edm
/// </summary>
public AuthorizationProvider AuthorizationProvider { get; }
//public CapabilitiesProvider CapabilitiesProvider { get; }
/// <summary>
/// Gets the Edm model.
/// </summary>
@ -143,6 +142,17 @@ namespace Microsoft.OpenApi.OData.Edm
}
}
/// <summary>
/// Find the Org.OData.Core.V1.HttpRequest for a given target.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="method">The method name.</param>
/// <returns>The <see cref="HttpRequest"/> or null.</returns>
public HttpRequest FindRequest(IEdmVocabularyAnnotatable target, string method)
{
return _httpRequestProvider?.GetHttpRequest(target, method);
}
/// <summary>
/// Finds the operations using the <see cref="IEdmEntityType"/>
/// </summary>
@ -187,24 +197,6 @@ namespace Microsoft.OpenApi.OData.Edm
}
}
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)
@ -236,20 +228,5 @@ namespace Microsoft.OpenApi.OData.Edm
}
_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;
}
}
}
}

View file

@ -39,9 +39,6 @@ namespace Microsoft.OpenApi.OData.Operation
if (Context.Settings.OperationId)
{
string key = "OperationImport." + EdmOperationImport.Name;
operation.OperationId += "OperationImport." + Context.GetIndex(key) + "-" + Utils.UpperFirstChar(EdmOperationImport.Name);
if (EdmOperationImport.IsActionImport())
{
operation.OperationId = "OperationImport." + EdmOperationImport.Name;

View file

@ -26,7 +26,7 @@ namespace Microsoft.OpenApi.OData.Operation
// Summary
operation.Summary = "Delete entity from " + EntitySet.Name;
// override the summary using the request.Description.
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
var request = Context.FindRequest(EntitySet, OperationType.ToString());
if (request != null && request.Description != null)
{
operation.Summary = request.Description;

View file

@ -4,7 +4,6 @@
// ------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OData.Edm;
@ -29,7 +28,7 @@ namespace Microsoft.OpenApi.OData.Operation
operation.Summary = "Get entity from " + EntitySet.Name + " by key";
// override the summary using the request.Description.
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
var request = Context.FindRequest(EntitySet, OperationType.ToString());
if (request != null && request.Description != null)
{
operation.Summary = request.Description;
@ -61,9 +60,6 @@ namespace Microsoft.OpenApi.OData.Operation
{
operation.Parameters.Add(parameter);
}
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
AppendCustomParameters(operation, request);
}
/// <inheritdoc/>
@ -99,15 +95,5 @@ namespace Microsoft.OpenApi.OData.Operation
};
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();
}
}
}
}

View file

@ -27,7 +27,7 @@ namespace Microsoft.OpenApi.OData.Operation
// Summary
operation.Summary = "Update entity in " + EntitySet.Name;
// override the summary using the request.Description.
var request = Context.FindRequest(EntitySet.EntityType(), OperationType.ToString());
var request = Context.FindRequest(EntitySet, OperationType.ToString());
if (request != null && request.Description != null)
{
operation.Summary = request.Description;

View file

@ -109,9 +109,6 @@ namespace Microsoft.OpenApi.OData.Operation
{
operation.Parameters.Add(parameter);
}
var request = Context.FindRequest(EntitySet, OperationType.ToString());
AppendCustomParameters(operation, request);
}
/// <inheritdoc/>

View file

@ -3,11 +3,13 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
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
{
@ -42,5 +44,29 @@ namespace Microsoft.OpenApi.OData.Operation
Context.AppendTag(tag);
}
/// <inheritdoc/>
protected override void SetSecurity(OpenApiOperation operation)
{
base.SetSecurity(operation);
var request = Context.FindRequest(EntitySet, OperationType.ToString());
if (request != null)
{
operation.Security = Context.CreateSecurityRequirements(request.SecuritySchemes).ToList();
}
}
/// <inheritdoc/>
protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
var request = Context.FindRequest(EntitySet, OperationType.ToString());
if (request != null)
{
AppendCustomParameters(operation, request);
}
}
}
}

View file

@ -169,7 +169,7 @@ namespace Microsoft.OpenApi.OData.Operation
Description = param.Description,
Schema = new OpenApiSchema
{
// Type = param.Type
Type = "string"
},
Required = param.Required ?? false
};

View file

@ -60,9 +60,6 @@ namespace Microsoft.OpenApi.OData.Operation
{
operation.Parameters.Add(parameter);
}
var request = Context.FindRequest(Singleton, OperationType.ToString());
AppendCustomParameters(operation, request);
}
/// <inheritdoc/>

View file

@ -3,11 +3,13 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
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
{
@ -45,5 +47,29 @@ namespace Microsoft.OpenApi.OData.Operation
Context.AppendTag(tag);
}
/// <inheritdoc/>
protected override void SetSecurity(OpenApiOperation operation)
{
base.SetSecurity(operation);
var request = Context.FindRequest(Singleton, OperationType.ToString());
if (request != null)
{
operation.Security = Context.CreateSecurityRequirements(request.SecuritySchemes).ToList();
}
}
/// <inheritdoc/>
protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
var request = Context.FindRequest(Singleton, OperationType.ToString());
if (request != null)
{
AppendCustomParameters(operation, request);
}
}
}
}

View file

@ -0,0 +1,308 @@
// ------------------------------------------------------------
// 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.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.OData.Annotations;
using Xunit;
namespace Microsoft.OpenApi.OData.Reader.Annotations.Tests
{
public class HttpRequestProviderTest
{
[Fact]
public void CtorThrowArgumentNullModel()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>("model", () => new HttpRequestProvider(model: null));
}
[Fact]
public void GetHttpRequestThrowArgumentNullTarget()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>("target",
() => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(target: null, method: "GET"));
}
[Fact]
public void GetHttpRequestThrowArgumentNullMethod()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>("method",
() => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(new EdmEntityContainer("NS", "Default"), method: null));
}
[Theory]
[InlineData("Customers")]
[InlineData("Me")]
public void GetHttpRequestsReturnsNullForTargetWithoutAnnotations(string name)
{
// Arrange
IEdmModel model = GetEdmModel("", "");
var httpRequestProvider = new HttpRequestProvider(model);
IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name);
Assert.NotNull(navigationSource);
// Act & Assert
var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable);
// Assert
Assert.Null(requests);
}
[Theory]
[InlineData("Customers")]
[InlineData("Me")]
public void GetHttpRequestsReturnsForEdmModelNavigationSourceWithAnnotations(string name)
{
// Arrange
string annotation = @"
<Annotation Term=""Org.OData.Core.V1.HttpRequests"">
<Collection>
<Record>
<PropertyValue Property=""Description"" />
<PropertyValue Property=""MethodDescription"" String=""Example"" />
<PropertyValue Property=""MethodType"" String=""DELETE"" />
<PropertyValue Property=""CustomHeaders"">
<Collection>
<Record>
<PropertyValue Property=""Name"" String=""Authorization"" />
<PropertyValue Property=""Description"" String=""String"" />
<PropertyValue Property=""Required"" Bool=""false"" />
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""CustomQueryOptions"">
<Collection />
</PropertyValue>
<PropertyValue Property=""HttpResponses"">
<Collection>
<Record>
<PropertyValue Property=""ResponseCode"" String=""204"" />
<PropertyValue Property=""Examples"">
<Record Type=""Org.OData.Core.V1.InlineExample"">
<PropertyValue Property=""InlineExample"" />
<PropertyValue Property=""Description"" />
</Record>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""SecuritySchemes"">
<Collection>
<Record>
<PropertyValue Property=""AuthorizationSchemeName"" String=""Delegated (work or school account)"" />
<PropertyValue Property=""RequiredScopes"">
<Collection>
<String>Directory.AccessAsUser.All</String>
</Collection>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
</Record>
<Record>
<PropertyValue Property=""Description"" />
<PropertyValue Property=""MethodDescription"" String=""Example"" />
<PropertyValue Property=""MethodType"" String=""GET"" />
<PropertyValue Property=""CustomHeaders"">
<Collection>
<Record>
<PropertyValue Property=""Name"" String=""Authorization"" />
<PropertyValue Property=""Description"" String=""String"" />
<PropertyValue Property=""Required"" Bool=""false"" />
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""CustomQueryOptions"">
<Collection />
</PropertyValue>
<PropertyValue Property=""HttpResponses"">
<Collection>
<Record>
<PropertyValue Property=""ResponseCode"" String=""200"" />
<PropertyValue Property=""Examples"">
<Record Type=""Org.OData.Core.V1.InlineExample"">
<PropertyValue Property=""InlineExample"" String=""{&#xD;&#xA; &quot;accountEnabled&quot;:false,&#xD;&#xA; &quot;deviceId&quot;:&quot;4c299165-6e8f-4b45-a5ba-c5d250a707ff&quot;,&#xD;&#xA; &quot;displayName&quot;:&quot;Test device&quot;,&#xD;&#xA; &quot;id&quot;: &quot;id-value&quot;,&#xD;&#xA; &quot;operatingSystem&quot;:&quot;linux&quot;,&#xD;&#xA; &quot;operatingSystemVersion&quot;:&quot;1&quot;&#xD;&#xA;}&#xA;"" />
<PropertyValue Property=""Description"" String=""application/json"" />
</Record>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""SecuritySchemes"">
<Collection>
<Record>
<PropertyValue Property=""AuthorizationSchemeName"" String=""Delegated (work or school account)"" />
<PropertyValue Property=""RequiredScopes"">
<Collection>
<String>Directory.Read.All</String>
<String>Directory.ReadWrite.All</String>
<String>Directory.AccessAsUser.All</String>
</Collection>
</PropertyValue>
</Record>
<Record>
<PropertyValue Property=""AuthorizationSchemeName"" String=""Application"" />
<PropertyValue Property=""RequiredScopes"">
<Collection>
<String>Device.ReadWrite.All</String>
<String>Directory.Read.All</String>
<String>Directory.ReadWrite.All</String>
</Collection>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
</Record>
<Record>
<PropertyValue Property=""Description"" />
<PropertyValue Property=""MethodDescription"" String=""PATCH Example"" />
<PropertyValue Property=""MethodType"" String=""PATCH"" />
<PropertyValue Property=""CustomHeaders"">
<Collection>
<Record>
<PropertyValue Property=""Name"" String=""Authorization"" />
<PropertyValue Property=""Description"" String=""String"" />
<PropertyValue Property=""Required"" Bool=""false"" />
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""CustomQueryOptions"">
<Collection />
</PropertyValue>
<PropertyValue Property=""HttpResponses"">
<Collection>
<Record>
<PropertyValue Property=""ResponseCode"" String=""204"" />
<PropertyValue Property=""Examples"">
<Record Type=""Org.OData.Core.V1.InlineExample"">
<PropertyValue Property=""InlineExample"" />
<PropertyValue Property=""Description"" />
</Record>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
<PropertyValue Property=""SecuritySchemes"">
<Collection>
<Record>
<PropertyValue Property=""AuthorizationSchemeName"" String=""Delegated (work or school account)"" />
<PropertyValue Property=""RequiredScopes"">
<Collection>
<String>Directory.ReadWrite.All</String>
<String>Directory.AccessAsUser.All</String>
</Collection>
</PropertyValue>
</Record>
</Collection>
</PropertyValue>
</Record>
</Collection>
</Annotation>";
IEdmModel model = GetEdmModel(annotation, annotation);
var httpRequestProvider = new HttpRequestProvider(model);
IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name);
Assert.NotNull(navigationSource);
// Act
var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable);
// Assert
Assert.NotEmpty(requests);
Assert.Equal(3, requests.Count());
// Act
var anotherRequests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable);
// Assert
Assert.True(ReferenceEquals(requests, anotherRequests));
// Act (PATCH)
var request = httpRequestProvider.GetHttpRequest(navigationSource as IEdmVocabularyAnnotatable, "PATCH");
// Assert
Assert.NotNull(request);
Assert.Equal("PATCH Example", request.MethodDescription);
Assert.NotNull(request.SecuritySchemes);
var securityScheme = Assert.Single(request.SecuritySchemes);
Assert.Equal("Delegated (work or school account)", securityScheme.AuthorizationSchemeName);
Assert.NotNull(securityScheme.RequiredScopes);
Assert.Equal(new[] { "Directory.ReadWrite.All", "Directory.AccessAsUser.All" }, securityScheme.RequiredScopes);
}
private static IEdmModel GetEdmModel(string entitySetAnnotation, string singletonAnnotation)
{
string template = @"<?xml version=""1.0"" encoding=""utf-16""?>
<edmx:Edmx xmlns:ags=""http://aggregator.microsoft.com/internal"" Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
<edmx:DataServices>
<Schema Namespace=""NS"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
<EntityType Name=""Customer"">
<Key>
<PropertyRef Name=""Id"" />
</Key>
<Property Name=""Id"" Type=""Edm.Int32"" Nullable=""false"" />
</EntityType>
<EntityContainer Name=""Container"">
<EntitySet Name=""Customers"" EntityType=""NS.Customer"">
{0}
</EntitySet>
<Singleton Name=""Me"" Type=""NS.Customer"" >
{1}
</Singleton>
</EntityContainer>
</Schema>
<Schema Namespace=""Org.OData.Core.V1"" Alias=""Core"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
<Term Name=""HttpRequests"" Type=""Collection(Core.HttpRequest)"" AppliesTo=""EntitySet Singleton ActionImport FunctionImport Action Function"">
<Annotation Term=""Core.Description"" String=""Describes possible HTTP requests"" />
<Annotation Term=""Core.LongDescription"" String=""The list need not be complete. It may be used to generate API documentation, so restricting it to the most common and most important responses may increase readability."" />
</Term>
<ComplexType Name=""HttpRequest"">
<Property Name=""Description"" Type=""Edm.String"" />
<!-- text such as ""For a specific user:"" to describe the http request-->
<Property Name=""Method"" Type=""Edm.String"" />
<Property Name=""CustomQueryOptions"" Type=""Collection(Core.CustomParameter)"" />
<Property Name=""CustomHeaders"" Type=""Collection(Core.CustomParameter)"" /> <!-- Map to Parameter in Operation as Header object.-->
<Property Name=""HttpResponses"" Type=""Collection(Core.HttpResponse)"" /> <!-- Map to Response object in Operation. -->
<Property Name=""SecuritySchemes"" Type=""Collection(Auth.SecurityScheme)""/>
</ComplexType>
<ComplexType Name=""HttpResponse"">
<Property Name=""ResponseCode"" Type=""Edm.String"" />
<Property Name=""Examples"" Type=""Collection(Core.Example)"" />
<Property Name=""Description"" Type=""Edm.String"" />
</ComplexType>
<ComplexType Name=""CustomParameter"">
<Property Name=""Name"" Type=""Edm.String"" Nullable=""false"" />
<Property Name=""Description"" Type=""Edm.String"" />
<Property Name=""DocumentationURL"" Type=""Edm.String"" />
<Property Name=""Required"" Type=""Edm.Boolean"" Nullable=""false"" />
<Property Name=""ExampleValues"" Type=""Collection(Core.Example)"" Nullable=""false"" />
</ComplexType>
<ComplexType Name=""Example"" Abstract=""true"">
<Property Name=""Description"" Type=""Edm.String"" Nullable=""false"" />
</ComplexType>
<ComplexType Name=""ExternalExample"" BaseType=""Core.Example"">
<Property Name=""ExternalValue"" Type=""Edm.String"" Nullable=""false"" />
</ComplexType>
<ComplexType Name=""InlineExample"" BaseType=""Core.Example"">
<Property Name=""InlineValue"" Type=""Edm.String"" Nullable=""false"" />
</ComplexType>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
";
string modelText = string.Format(template, entitySetAnnotation, singletonAnnotation);
return CsdlReader.Parse(XElement.Parse(modelText).CreateReader());
}
}
}

View file

@ -20,6 +20,10 @@ namespace UpdateDocs
{
static int Main(string[] args)
{
if (!Test())
{
return 0;
}
// we assume the path are existed for simplicity.
string path = Directory.GetCurrentDirectory();
string csdl = path + "../../../../../../docs/csdl";
@ -75,6 +79,15 @@ namespace UpdateDocs
return 0;
}
public static bool Test()
{
var model = LoadEdmModel(@"E:\work\OpenApi\metadata_withRequestTerms.xml");
OpenApiDocument document = model.ConvertToOpenApi();
string output = @"E:\work\OpenApi\metadata_withRequestTerms.json";
File.WriteAllText(output, document.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0));
return false;
}
public static IEdmModel LoadEdmModel(string file)
{
try