OpenAPI.NET.OData/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
2018-08-21 14:42:55 -07:00

237 lines
7.7 KiB
C#

// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
using System;
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.EnableKeyAsSegment ?? 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;
}
}
}
}