clean codes

This commit is contained in:
Sam Xu 2017-11-10 19:31:01 -08:00
parent 436f7f3a76
commit 9f4a32271d
18 changed files with 588 additions and 559 deletions

View file

@ -4,12 +4,15 @@
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Represents an Open API document element.
/// </summary>
internal interface IOpenApiElement
internal interface IOpenApiDocumentGenerator
{
OpenApiDocument Generate();
}
}

View file

@ -1,48 +0,0 @@
//---------------------------------------------------------------------
// <copyright file="EdmHelper.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Commons;
using System.Diagnostics;
namespace Microsoft.OpenApi.OData
{
internal static class EdmHelper
{
public static string GetOpenApiTypeName(this IEdmTypeReference edmType)
{
Debug.Assert(edmType != null);
return edmType.Definition.GetOpenApiTypeName();
}
public static string GetOpenApiTypeName(this IEdmType edmType)
{
Debug.Assert(edmType != null);
switch (edmType.TypeKind)
{
case EdmTypeKind.Collection:
return AnyTypeKind.Array.GetDisplayName();
case EdmTypeKind.Complex:
case EdmTypeKind.Entity:
case EdmTypeKind.EntityReference:
return AnyTypeKind.Object.GetDisplayName();
case EdmTypeKind.Enum:
return "string";
case EdmTypeKind.Primitive:
return ((IEdmPrimitiveType)(edmType)).GetOpenApiDataType().GetCommonName();
default:
return AnyTypeKind.Null.GetDisplayName();
}
}
}
}

View file

@ -1,139 +0,0 @@
//---------------------------------------------------------------------
// <copyright file="EdmOpenApiDocumentGenerator.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// An class used to covert Edm model to <see cref="OpenApiDocument"/>
/// </summary>
internal class EdmOpenApiDocumentGenerator : EdmOpenApiGenerator
{
private OpenApiDocument _openApiDoc;
private EdmOpenApiComponentsGenerator _componentsGenerator;
private EdmOpenApiPathsGenerator _pathsGenerator;
/// <summary>
/// Initializes a new instance of the <see cref="EdmOpenApiDocumentGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public EdmOpenApiDocumentGenerator(IEdmModel model, OpenApiWriterSettings settings)
: base(model, settings)
{
_componentsGenerator = new EdmOpenApiComponentsGenerator(model, settings);
_pathsGenerator = new EdmOpenApiPathsGenerator(model, settings);
}
/// <summary>
/// Generate Open Api document.
/// </summary>
/// <returns>The <see cref="OpenApiDocument"/> object.</returns>
public virtual OpenApiDocument Generate()
{
if (_openApiDoc == null)
{
_openApiDoc = new OpenApiDocument
{
Info = CreateInfo(),
Servers = CreateServers(),
Paths = CreatePaths(),
Components = CreateComponents(),
SecurityRequirements = CreateSecurity(),
Tags = CreateTags()
};
}
return _openApiDoc;
}
/// <summary>
/// Create <see cref="OpenApiInfo"/> object.
/// </summary>
/// <returns>The info object.</returns>
private OpenApiInfo CreateInfo()
{
return new OpenApiInfo
{
Title = "OData Service for namespace " + Model.DeclaredNamespaces.FirstOrDefault(),
Version = Settings.Version,
Description = "This OData service is located at " + Settings.BaseUri?.OriginalString
};
}
/// <summary>
/// Create the collection of <see cref="OpenApiServer"/> object.
/// </summary>
/// <returns>The servers object.</returns>
private IList<OpenApiServer> CreateServers()
{
return new List<OpenApiServer>
{
new OpenApiServer
{
Url = string.Empty
}
};
}
/// <summary>
/// Create the <see cref="OpenApiPaths"/> object.
/// </summary>
/// <returns>The paths object.</returns>
private OpenApiPaths CreatePaths()
{
return _pathsGenerator.Generate();
}
// <summary>
/// Create the <see cref="OpenApiComponents"/> object.
/// </summary>
/// <returns>The components object.</returns>
private OpenApiComponents CreateComponents()
{
return _componentsGenerator.Generate();
}
// <summary>
/// Create the collection of <see cref="OpenApiSecurity"/> object.
/// </summary>
/// <returns>The security object.</returns>
private IList<OpenApiSecurityRequirement> CreateSecurity()
{
return null;
}
// <summary>
/// Create the collection of <see cref="OpenApiTag"/> object.
/// </summary>
/// <returns>The tag object.</returns>
private IList<OpenApiTag> CreateTags()
{
IList<OpenApiTag> tags = new List<OpenApiTag>();
if (Model.EntityContainer != null)
{
foreach (IEdmEntitySet entitySet in Model.EntityContainer.EntitySets())
{
tags.Add(new OpenApiTag
{
Name = entitySet.Name
});
}
}
return tags;
}
}
}

View file

@ -1,37 +0,0 @@
//---------------------------------------------------------------------
// <copyright file="EdmOpenApiGenerator.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OData.Edm;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Base class for Edm to Open Api generator.
/// </summary>
internal abstract class EdmOpenApiGenerator
{
/// <summary>
/// The Edm model.
/// </summary>
protected IEdmModel Model { get; }
/// <summary>
/// The Open Api writer setting.
/// </summary>
public OpenApiWriterSettings Settings { get; }
/// <summary>
/// Initializes a new instance of the <see cref="EdmOpenApiGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
protected EdmOpenApiGenerator(IEdmModel model, OpenApiWriterSettings settings)
{
Model = model ?? throw Error.ArgumentNull(nameof(model));
Settings = settings ?? throw Error.ArgumentNull(nameof(settings));
}
}
}

View file

@ -1,95 +0,0 @@
//---------------------------------------------------------------------
// <copyright file="EdmOpenApiPathsGenerator.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Visit Edm model to generate <see cref="OpenApiPaths"/>
/// </summary>
internal class EdmOpenApiPathsGenerator : EdmOpenApiGenerator
{
private OpenApiPaths _paths;
private EdmNavigationSourceGenerator _nsGenerator;
/// <summary>
/// Initializes a new instance of the <see cref="EdmOpenApiPathsGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public EdmOpenApiPathsGenerator(IEdmModel model, OpenApiWriterSettings settings)
: base(model, settings)
{
_nsGenerator = new EdmNavigationSourceGenerator(model, settings);
}
/// <summary>
/// Create the <see cref="OpenApiPaths"/>
/// </summary>
/// <returns>the paths object.</returns>
public OpenApiPaths Generate()
{
if (_paths == null)
{
_paths = new OpenApiPaths();
if (Model.EntityContainer != null)
{
foreach (var element in Model.EntityContainer.Elements)
{
switch (element.ContainerElementKind)
{
case EdmContainerElementKind.EntitySet:
IEdmEntitySet entitySet = element as IEdmEntitySet;
if (entitySet != null)
{
foreach (var item in _nsGenerator.CreatePaths(entitySet))
{
_paths.Add(item.Key, item.Value);
}
}
break;
case EdmContainerElementKind.Singleton:
IEdmSingleton singleton = element as IEdmSingleton;
if (singleton != null)
{
foreach (var item in _nsGenerator.CreatePaths(singleton))
{
_paths.Add(item.Key, item.Value);
}
}
break;
case EdmContainerElementKind.FunctionImport:
IEdmFunctionImport functionImport = element as IEdmFunctionImport;
if (functionImport != null)
{
var functionImportPathItem = functionImport.CreatePathItem();
_paths.Add(functionImport.CreatePathItemName(), functionImportPathItem);
}
break;
case EdmContainerElementKind.ActionImport:
IEdmActionImport actionImport = element as IEdmActionImport;
if (actionImport != null)
{
var functionImportPathItem = actionImport.CreatePathItem();
_paths.Add(actionImport.CreatePathItemName(), functionImportPathItem);
}
break;
}
}
}
}
return _paths;
}
}
}

View file

@ -1,224 +0,0 @@
//---------------------------------------------------------------------
// <copyright file="EdmValueWriter.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Xml;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Contains methods to convert primitive values to their string representation.
/// </summary>
internal static class EdmValueWriter
{
/// <summary>
/// Characters used in string representations of hexadecimal values
/// </summary>
private static char[] Hex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/// <summary>
/// Converts the IEdmPrimitiveValue to a String.
/// </summary>
/// <param name="v">The value to convert.</param>
/// <returns>A string representation of the IEdmPrimitiveValue.</returns>
internal static string PrimitiveValueAsXml(IEdmPrimitiveValue v)
{
switch (v.ValueKind)
{
case EdmValueKind.Boolean:
return BooleanAsXml(((IEdmBooleanValue)v).Value);
case EdmValueKind.Integer:
return LongAsXml(((IEdmIntegerValue)v).Value);
case EdmValueKind.Floating:
return FloatAsXml(((IEdmFloatingValue)v).Value);
case EdmValueKind.Guid:
return GuidAsXml(((IEdmGuidValue)v).Value);
case EdmValueKind.Binary:
return BinaryAsXml(((IEdmBinaryValue)v).Value);
case EdmValueKind.Decimal:
return DecimalAsXml(((IEdmDecimalValue)v).Value);
case EdmValueKind.String:
return StringAsXml(((IEdmStringValue)v).Value);
case EdmValueKind.DateTimeOffset:
return DateTimeOffsetAsXml(((IEdmDateTimeOffsetValue)v).Value);
case EdmValueKind.Date:
return DateAsXml(((IEdmDateValue)v).Value);
case EdmValueKind.Duration:
return DurationAsXml(((IEdmDurationValue)v).Value);
case EdmValueKind.TimeOfDay:
return TimeOfDayAsXml(((IEdmTimeOfDayValue)v).Value);
default:
return null;
}
}
/// <summary>
/// Converts the String to a String.
/// </summary>
/// <param name="s">The value to convert.</param>
/// <returns>The value to convert.</returns>
internal static string StringAsXml(string s)
{
return s;
}
/// <summary>
/// Converts the Byte[] to a String.
/// </summary>
/// <param name="binary">The value to convert.</param>
/// <returns>A string representation of the Byte[].</returns>
internal static string BinaryAsXml(byte[] binary)
{
var chars = new char[binary.Length * 2];
for (int i = 0; i < binary.Length; ++i)
{
chars[i << 1] = Hex[binary[i] >> 4];
chars[i << 1 | 1] = Hex[binary[i] & 0x0F];
}
return new string(chars);
}
/// <summary>
/// Converts the Boolean to a String.
/// </summary>
/// <param name="b">The value to convert.</param>
/// <returns>A string representation of the Boolean, that is, "true" or "false".</returns>
internal static string BooleanAsXml(bool b)
{
return XmlConvert.ToString(b);
}
/// <summary>
/// Converts the Boolean? to a String.
/// </summary>
/// <param name="b">The value to convert.</param>
/// <returns>A string representation of the Boolean, that is, "true" or "false".</returns>
internal static string BooleanAsXml(bool? b)
{
Debug.Assert(b.HasValue, "Serialized nullable boolean must have value.");
return BooleanAsXml(b.Value);
}
/// <summary>
/// Converts the Int32 to a String.
/// </summary>
/// <param name="i">The value to convert</param>
/// <returns>A string representation of the Int32.</returns>
internal static string IntAsXml(int i)
{
return XmlConvert.ToString(i);
}
/// <summary>
/// Converts the Int32? to a String.
/// </summary>
/// <param name="i">The value to convert</param>
/// <returns>A string representation of the Int32.</returns>
internal static string IntAsXml(int? i)
{
Debug.Assert(i.HasValue, "Serialized nullable integer must have value.");
return IntAsXml(i.Value);
}
/// <summary>
/// Converts the Int64 to a String.
/// </summary>
/// <param name="l">The value to convert.</param>
/// <returns>A string representation of the Int64.</returns>
internal static string LongAsXml(long l)
{
return XmlConvert.ToString(l);
}
/// <summary>
/// Converts the Double to a String.
/// </summary>
/// <param name="f">The value to convert.</param>
/// <returns>A string representation of the Double.</returns>
internal static string FloatAsXml(double f)
{
return XmlConvert.ToString(f);
}
/// <summary>
/// Converts the Decimal to a String.
/// </summary>
/// <param name="d">The value to convert.</param>
/// <returns>A string representation of the Decimal.</returns>
internal static string DecimalAsXml(decimal d)
{
return XmlConvert.ToString(d);
}
/// <summary>
/// Converts the TimeSpan to a String.
/// </summary>
/// <param name="d">The value to convert.</param>
/// <returns>A string representation of the TimeSpan.</returns>
internal static string DurationAsXml(TimeSpan d)
{
return XmlConvert.ToString(d);
}
/// <summary>
/// Converts the DateTimeOffset to a String.
/// </summary>
/// <param name="d">The System.DateTimeOffset to be converted.</param>
/// <returns>A System.String representation of the supplied System.DateTimeOffset.</returns>
internal static string DateTimeOffsetAsXml(DateTimeOffset d)
{
var value = XmlConvert.ToString(d);
return value;
}
/// <summary>
/// Converts the Date to a String.
/// </summary>
/// <param name="d">The <see cref="Microsoft.OData.Edm.Date"/> to be converted</param>
/// <returns>A System.String representation of the supplied <see cref="Microsoft.OData.Edm.Date"/>.</returns>
internal static string DateAsXml(Date d)
{
var value = d.ToString();
return value;
}
/// <summary>
/// Converts the TimeOfDay to a String.
/// </summary>
/// <param name="time">The <see cref="Microsoft.OData.Edm.TimeOfDay"/> to be converted</param>
/// <returns>A System.String representation of the supplied <see cref="Microsoft.OData.Edm.TimeOfDay"/>.</returns>
internal static string TimeOfDayAsXml(TimeOfDay time)
{
var value = time.ToString();
return value;
}
/// <summary>
/// Converts the Guid to a String.
/// </summary>
/// <param name="g">The value to convert.</param>
/// <returns>A string representation of the Guid.</returns>
internal static string GuidAsXml(Guid g)
{
return XmlConvert.ToString(g);
}
/// <summary>
/// Converts the Uri to a String.
/// </summary>
/// <param name="uri">The value to convert.</param>
/// <returns>A string representation of the Uri.</returns>
internal static string UriAsXml(Uri uri)
{
Debug.Assert(uri != null, "uri != null");
return uri.OriginalString;
}
}
}

View file

@ -0,0 +1,100 @@
//---------------------------------------------------------------------
// <copyright file="EdmHelper.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OData.Edm.Vocabularies.V1;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Commons;
using System.Diagnostics;
using System.Linq;
namespace Microsoft.OpenApi.OData
{
internal static class EdmHelper
{
public static string GetDescription(this IEdmModel model, IEdmEntitySet entitySet)
{
}
public static string GetDescription(this IEdmModel model, IEdmVocabularyAnnotatable element)
{
if (model == null || element == null)
{
return null;
}
IEdmVocabularyAnnotation annotation =
model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(
element, CoreVocabularyModel.DescriptionTerm).FirstOrDefault();
if (annotation != null)
{
IEdmStringConstantExpression stringConstant = annotation.Value as IEdmStringConstantExpression;
if (stringConstant != null)
{
return stringConstant.Value;
}
}
return null;
}
public static string GetEntityContainerCoreDescription(this IEdmModel model)
{
if (model == null || model.EntityContainer == null)
{
return null;
}
IEdmVocabularyAnnotation annotation =
model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(
model.EntityContainer, CoreVocabularyModel.DescriptionTerm).FirstOrDefault();
if (annotation != null)
{
IEdmStringConstantExpression stringConstant = annotation.Value as IEdmStringConstantExpression;
if (stringConstant != null)
{
return stringConstant.Value;
}
}
return null;
}
public static string GetOpenApiTypeName(this IEdmTypeReference edmType)
{
Debug.Assert(edmType != null);
return edmType.Definition.GetOpenApiTypeName();
}
public static string GetOpenApiTypeName(this IEdmType edmType)
{
Debug.Assert(edmType != null);
switch (edmType.TypeKind)
{
case EdmTypeKind.Collection:
return AnyTypeKind.Array.GetDisplayName();
case EdmTypeKind.Complex:
case EdmTypeKind.Entity:
case EdmTypeKind.EntityReference:
return AnyTypeKind.Object.GetDisplayName();
case EdmTypeKind.Enum:
return "string";
case EdmTypeKind.Primitive:
return ((IEdmPrimitiveType)(edmType)).GetOpenApiDataType().GetCommonName();
default:
return AnyTypeKind.Null.GetDisplayName();
}
}
}
}

View file

@ -0,0 +1,121 @@
//---------------------------------------------------------------------
// <copyright file="EdmModelOpenApiExtensions.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System.IO;
using Microsoft.OData.Edm;
using Microsoft.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Writers;
using System;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Extension methods to write Entity Data Model (EDM) to Open API.
/// </summary>
public static class EdmModelOpenApiMappingExtensions
{
/// <summary>
/// Outputs Edm model to an Open API artifact to the give stream.
/// </summary>
/// <param name="model">Edm model to be written.</param>
/// <param name="stream">The output stream.</param>
/// <param name="target">The Open API target.</param>
/// <param name="settings">Settings for the generated Open API.</param>
public static OpenApiDocument Mapping(this IEdmModel model)
{
if (model == null)
{
throw Error.ArgumentNull(nameof(model));
}
return new OpenApiDocument();
}
public static OpenApiDocument Mapping(this IEdmModel model, Action<OpenApiDocument> configure)
{
if (model == null)
{
throw Error.ArgumentNull(nameof(model));
}
return new OpenApiDocument();
}
/// <summary>
/// Outputs Edm model to an Open API artifact to the give text writer.
/// </summary>
/// <param name="model">Edm model to be written.</param>
/// <param name="writer">The output text writer.</param>
/// <param name="target">The Open API target.</param>
/// <param name="settings">Settings for the generated Open API.</param>
public static void WriteOpenApi(this IEdmModel model, TextWriter writer, OpenApiFormat target, OpenApiWriterSettings settings = null)
{
if (model == null)
{
throw Error.ArgumentNull(nameof(model));
}
if (writer == null)
{
throw Error.ArgumentNull(nameof(writer));
}
IOpenApiWriter openApiWriter = BuildWriter(writer, target);
model.WriteOpenApi(openApiWriter, settings);
}
/// <summary>
/// Outputs an Open API artifact to the provided Open Api writer.
/// </summary>
/// <param name="model">Model to be written.</param>
/// <param name="writer">The generated Open API writer <see cref="IOpenApiWriter"/>.</param>
/// <param name="settings">Settings for the generated Open API.</param>
public static void WriteOpenApi(this IEdmModel model, IOpenApiWriter writer, OpenApiWriterSettings settings = null)
{
if (model == null)
{
throw Error.ArgumentNull("model");
}
if (writer == null)
{
throw Error.ArgumentNull("writer");
}
if (settings == null)
{
settings = new OpenApiWriterSettings();
}
EdmOpenApiDocumentGenerator converter = new EdmOpenApiDocumentGenerator(model, settings);
OpenApiDocument doc = converter.Generate();
doc.Serialize(writer);
}
private static IOpenApiWriter BuildWriter(Stream stream, OpenApiFormat target)
{
StreamWriter writer = new StreamWriter(stream)
{
NewLine = "\n"
};
return BuildWriter(writer, target);
}
private static IOpenApiWriter BuildWriter(TextWriter writer, OpenApiFormat target)
{
if (target == OpenApiFormat.Json)
{
return new OpenApiJsonWriter(writer);
}
else
{
return new OpenApiYamlWriter(writer);
}
}
}
}

View file

@ -0,0 +1,48 @@
//---------------------------------------------------------------------
// <copyright file="EdmModelOpenApiExtensions.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System.IO;
using Microsoft.OData.Edm;
using Microsoft.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Writers;
using System;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Extension methods to write Entity Data Model (EDM) to Open API.
/// </summary>
public static class EdmModelOpenApiMappingExtensions
{
/// <summary>
/// Outputs Edm model to an Open API artifact to the give stream.
/// </summary>
/// <param name="model">Edm model to be written.</param>
/// <param name="stream">The output stream.</param>
/// <param name="target">The Open API target.</param>
/// <param name="settings">Settings for the generated Open API.</param>
public static OpenApiDocument Convert(this IEdmModel model)
{
if (model == null)
{
throw Error.ArgumentNull(nameof(model));
}
return new OpenApiDocument();
}
public static OpenApiDocument Convert(this IEdmModel model, Action<OpenApiDocument> configure)
{
if (model == null)
{
throw Error.ArgumentNull(nameof(model));
}
return new OpenApiDocument();
}
}
}

View file

@ -19,6 +19,14 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Compile Remove="EdmModelOpenApiMappingExtensions.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="OpenApiPathsGenerator.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.OData.Edm" Version="7.3.1" />
</ItemGroup>

View file

@ -6,19 +6,23 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
using System;
namespace Microsoft.OpenApi.OData
{
internal static class ODataOpenApiConvert
/// <summary>
///
/// </summary>
public static class EdmOpenApiExtensions
{
public static OpenApiDocument ConvertTo(this IEdmModel model)
public static OpenApiDocument Convert(this IEdmModel model)
{
return model.ConvertTo(new OpenApiWriterSettings());
return model.Convert(configure: null);
}
public static OpenApiDocument ConvertTo(this IEdmModel model, OpenApiWriterSettings settings)
public static OpenApiDocument Convert(this IEdmModel model, Action<OpenApiDocument> configure)
{
return new EdmOpenApiDocumentGenerator(model, settings).Generate();
return new OpenApiDocumentGenerator(model, settings).Generate();
}
}
}

View file

@ -14,17 +14,16 @@ namespace Microsoft.OpenApi.OData
/// <summary>
/// Visit Edm model to generate <see cref="OpenApiComponents"/>
/// </summary>
internal class EdmOpenApiComponentsGenerator : EdmOpenApiGenerator
internal class OpenApiComponentsGenerator
{
private OpenApiComponents _components;
/// <summary>
/// Initializes a new instance of the <see cref="EdmOpenApiComponentsGenerator" /> class.
/// Initializes a new instance of the <see cref="OpenApiComponentsGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public EdmOpenApiComponentsGenerator(IEdmModel model, OpenApiWriterSettings settings)
: base(model, settings)
public OpenApiComponentsGenerator(IEdmModel model)
{
}

View file

@ -0,0 +1,182 @@
//---------------------------------------------------------------------
// <copyright file="EdmOpenApiDocumentGenerator.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// A class used to covert Edm model to <see cref="OpenApiDocument"/>
/// </summary>
internal class OpenApiDocumentGenerator
{
private OpenApiDocument _openApiDoc;
private OpenApiComponentsGenerator _componentsGenerator;
private OpenApiPathsGenerator _pathsGenerator;
/// <summary>
/// The Edm model.
/// </summary>
protected IEdmModel Model { get; }
private Action<OpenApiDocument> _configure;
/// <summary>
/// Initializes a new instance of the <see cref="EdmOpenApiDocumentGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public OpenApiDocumentGenerator(IEdmModel model, Action<OpenApiDocument> configure)
{
Model = model;
_configure = configure;
_componentsGenerator = new OpenApiComponentsGenerator(model);
_pathsGenerator = new OpenApiPathsGenerator(model);
}
/// <summary>
/// Generate Open Api document.
/// </summary>
/// <returns>The <see cref="OpenApiDocument"/> object.</returns>
public OpenApiDocument Generate()
{
OpenApiDocument document = new OpenApiDocument
{
SpecVersion = new Version(3, 0, 0),
Info = CreateInfo(),
Servers = CreateServers(),
Paths = CreatePaths(),
Components = CreateComponents(),
Tags = CreateTags()
};
_configure?.Invoke(document);
return document;
}
/// <summary>
/// Create <see cref="OpenApiInfo"/> object.
/// </summary>
/// <returns>The info object.</returns>
private OpenApiInfo CreateInfo()
{
// The value of info is an Info Object,
// It contains the fields title and version, and optionally the field description.
return new OpenApiInfo
{
// The value of title is the value of the unqualified annotation Core.Description
// of the main schema or the entity container of the OData service.
// If no Core.Description is present, a default title has to be provided as this is a required OpenAPI field.
Title = "OData Service for namespace " + Model.DeclaredNamespaces.FirstOrDefault(),
// The value of version is the value of the annotation Core.SchemaVersion(see[OData - VocCore]) of the main schema.
// If no Core.SchemaVersion is present, a default version has to be provided as this is a required OpenAPI field.
Version = new Version(1, 0, 0),
// The value of description is the value of the annotation Core.LongDescription
// of the main schema or the entity container.
// While this field is optional, it prominently appears in OpenAPI exploration tools,
// so a default description should be provided if no Core.LongDescription annotation is present.
Description = "This OData service is located at " + Settings.BaseUri?.OriginalString
};
}
/// <summary>
/// Create the collection of <see cref="OpenApiServer"/> object.
/// </summary>
/// <returns>The servers object.</returns>
private IList<OpenApiServer> CreateServers()
{
// The value of servers is an array of Server Objects.
// It contains one object with a field url.
// The value of url is a string cotaining the service root URL without the trailing forward slash.
return new List<OpenApiServer>
{
new OpenApiServer
{
Url = string.Empty
}
};
}
/// <summary>
/// Create the <see cref="OpenApiPaths"/> object.
/// </summary>
/// <returns>The paths object.</returns>
private OpenApiPaths CreatePaths()
{
return _pathsGenerator.Generate();
}
// <summary>
/// Create the <see cref="OpenApiComponents"/> object.
/// </summary>
/// <returns>The components object.</returns>
private OpenApiComponents CreateComponents()
{
return _componentsGenerator.Generate();
}
// <summary>
/// Create the collection of <see cref="OpenApiTag"/> object.
/// </summary>
/// <returns>The tag object.</returns>
private IList<OpenApiTag> CreateTags()
{
// The value of tags is an array of Tag Objects.
// For an OData service the natural groups are entity sets and singletons,
// so the tags array contains one Tag Object per entity set and singleton in the entity container.
IList<OpenApiTag> tags = new List<OpenApiTag>();
if (Model.EntityContainer != null)
{
foreach (IEdmEntityContainerElement element in Model.EntityContainer.Elements)
{
switch(element.ContainerElementKind)
{
case EdmContainerElementKind.EntitySet: // entity set
IEdmEntitySet entitySet = (IEdmEntitySet)element;
tags.Add(new OpenApiTag
{
Name = entitySet.Name,
Description = Model.GetDescription(entitySet)
});
break;
case EdmContainerElementKind.Singleton: // singleton
IEdmSingleton singleton = (IEdmSingleton)element;
tags.Add(new OpenApiTag
{
Name = singleton.Name,
Description = Model.GetDescription(singleton)
});
break;
// The tags array can contain additional Tag Objects for other logical groups,
// e.g. for action imports or function imports that are not associated with an entity set.
case EdmContainerElementKind.ActionImport: // Action Import
break;
case EdmContainerElementKind.FunctionImport: // Function Import
break;
}
}
}
// Tags is optional.
return tags.Any() ? tags : null;
}
}
}

View file

@ -11,18 +11,20 @@ using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
internal class EdmNavigationSourceGenerator : EdmOpenApiGenerator
internal class OpenApiPathItemGenerator
{
public IDictionary<IEdmTypeReference, IEdmOperation> _boundOperations;
private IDictionary<IEdmTypeReference, IEdmOperation> _boundOperations;
private IEdmModel _model;
/// <summary>
/// Initializes a new instance of the <see cref="EdmNavigationSourceGenerator" /> class.
/// Initializes a new instance of the <see cref="OpenApiPathItemGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public EdmNavigationSourceGenerator(IEdmModel model, OpenApiWriterSettings settings)
: base(model, settings)
public OpenApiPathItemGenerator(IEdmModel model)
{
_model = model;
_boundOperations = new Dictionary<IEdmTypeReference, IEdmOperation>();
foreach (var edmOperation in model.SchemaElements.OfType<IEdmOperation>().Where(e => e.IsBound))
{
@ -31,11 +33,25 @@ namespace Microsoft.OpenApi.OData
}
}
/// <summary>
/// Path items for Entity Sets.
/// Each entity set is represented as a name/value pair
/// whose name is the service-relative resource path of the entity set prepended with a forward slash,
/// and whose value is a Path Item Object, see [OpenAPI].
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="entitySet">The Edm entity set.</param>
/// <returns>The path items.</returns>
public IDictionary<string, OpenApiPathItem> CreatePaths(IEdmEntitySet entitySet)
{
if (entitySet == null)
{
return null;
}
IDictionary<string, OpenApiPathItem> paths = new Dictionary<string, OpenApiPathItem>();
// itself
// entity set
OpenApiPathItem pathItem = new OpenApiPathItem();
pathItem.AddOperation(OperationType.Get, entitySet.CreateGetOperationForEntitySet());

View file

@ -0,0 +1,91 @@
//---------------------------------------------------------------------
// <copyright file="EdmOpenApiPathsGenerator.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
namespace Microsoft.OpenApi.OData
{
/// <summary>
/// Visit Edm model to generate <see cref="OpenApiPaths"/>
/// </summary>
internal class OpenApiPathsGenerator
{
private OpenApiPathItemGenerator _nsGenerator;
private IEdmModel _model;
/// <summary>
/// Initializes a new instance of the <see cref="OpenApiPathsGenerator" /> class.
/// </summary>
/// <param name="model">The Edm model.</param>
/// <param name="settings">The Open Api writer settings.</param>
public OpenApiPathsGenerator(IEdmModel model)
{
_model = model;
_nsGenerator = new OpenApiPathItemGenerator(model);
}
/// <summary>
/// Create the <see cref="OpenApiPaths"/>
/// </summary>
/// <returns>the paths object.</returns>
public OpenApiPaths Generate()
{
OpenApiPaths paths = new OpenApiPaths();
if (_model.EntityContainer != null)
{
foreach (var element in _model.EntityContainer.Elements)
{
switch (element.ContainerElementKind)
{
case EdmContainerElementKind.EntitySet:
IEdmEntitySet entitySet = element as IEdmEntitySet;
if (entitySet != null)
{
foreach (var item in _nsGenerator.CreatePaths(entitySet))
{
paths.Add(item.Key, item.Value);
}
}
break;
case EdmContainerElementKind.Singleton:
IEdmSingleton singleton = element as IEdmSingleton;
if (singleton != null)
{
foreach (var item in _nsGenerator.CreatePaths(singleton))
{
paths.Add(item.Key, item.Value);
}
}
break;
case EdmContainerElementKind.FunctionImport:
IEdmFunctionImport functionImport = element as IEdmFunctionImport;
if (functionImport != null)
{
var functionImportPathItem = functionImport.CreatePathItem();
paths.Add(functionImport.CreatePathItemName(), functionImportPathItem);
}
break;
case EdmContainerElementKind.ActionImport:
IEdmActionImport actionImport = element as IEdmActionImport;
if (actionImport != null)
{
var functionImportPathItem = actionImport.CreatePathItem();
paths.Add(actionImport.CreatePathItemName(), functionImportPathItem);
}
break;
}
}
}
return paths;
}
}
}