diff --git a/.github/workflows/validate-descriptions.yml b/.github/workflows/validate-descriptions.yml
new file mode 100644
index 000000000..a9a0d36df
--- /dev/null
+++ b/.github/workflows/validate-descriptions.yml
@@ -0,0 +1,36 @@
+name: OpenAPI Parser Validation for latest OpenAPI docs
+
+on:
+ push:
+ branches: [ main, support/v1 ]
+ pull_request:
+ branches: [ main, support/v1 ]
+
+jobs:
+
+ list-descriptions:
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.set-descriptions.outputs.matrix }}
+ steps:
+ - uses: actions/checkout@v4
+ - id: set-descriptions
+ run: echo "::set-output name=matrix::$(ls test/**/Resources/*.{json,yaml} | sed 's/.*\///' | jq -R -s -c 'split("\n")[:-1]')"
+
+ build:
+ needs: list-descriptions
+ strategy:
+ matrix:
+ descriptions: ${{ fromJson(needs.list-descriptions.outputs.matrix) }}
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Validate description with redocly
+ uses: fluximus-prime/redocly-cli-github-action@v1
+ with:
+ args: 'lint test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/${{ matrix.descriptions }} --skip-rule operation-4xx-response --skip-rule no-server-trailing-slash --skip-rule no-unused-components --skip-rule security-defined --skip-rule info-license-url --skip-rule info-license --skip-rule no-empty-servers --skip-rule operation-summary --skip-rule tag-description --max-problems 1000'
\ No newline at end of file
diff --git a/docs/oas3_0_0/TripService.json b/docs/oas3_0_0/TripService.json
index c9f2082a3..5e9134b98 100644
--- a/docs/oas3_0_0/TripService.json
+++ b/docs/oas3_0_0/TripService.json
@@ -38,7 +38,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -58,7 +57,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -76,7 +74,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -172,7 +169,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -190,7 +186,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -324,7 +319,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -348,7 +342,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -368,7 +361,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -464,7 +456,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -484,7 +475,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -711,7 +701,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -741,7 +730,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -815,7 +803,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -845,7 +832,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -988,7 +974,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1026,7 +1011,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1056,7 +1040,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1127,7 +1110,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1404,7 +1386,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1436,7 +1417,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1461,7 +1441,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1530,7 +1509,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1650,7 +1628,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1688,7 +1665,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1718,7 +1694,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1817,7 +1792,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1847,7 +1821,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -1979,7 +1952,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2009,7 +1981,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2196,7 +2167,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2234,7 +2204,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2264,7 +2233,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2345,7 +2313,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2688,7 +2655,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2720,7 +2686,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2745,7 +2710,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2824,7 +2788,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2956,7 +2919,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -2994,7 +2956,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3024,7 +2985,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3123,7 +3083,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3153,7 +3112,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3285,7 +3243,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3315,7 +3272,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3502,7 +3458,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3540,7 +3495,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3570,7 +3524,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3651,7 +3604,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -3994,7 +3946,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -4026,7 +3977,6 @@
"name": "$select",
"in": "query",
"description": "Select properties to be returned",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -4051,7 +4001,6 @@
"name": "$expand",
"in": "query",
"description": "Expand related entities",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
@@ -4130,7 +4079,6 @@
"name": "$orderby",
"in": "query",
"description": "Order items by property values",
- "style": "form",
"explode": false,
"schema": {
"uniqueItems": true,
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs
index 0c1e2ffa2..92e46b120 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs
@@ -15,183 +15,177 @@ internal static class Constants
///
/// application/json
///
- public static string ApplicationJsonMediaType = "application/json";
+ public const string ApplicationJsonMediaType = "application/json";
///
/// application/xml
///
- public static string ApplicationXmlMediaType = "application/xml";
+ public const string ApplicationXmlMediaType = "application/xml";
///
/// application/octet-stream
///
- public static string ApplicationOctetStreamMediaType = "application/octet-stream";
+ public const string ApplicationOctetStreamMediaType = "application/octet-stream";
///
/// Status code class: 2XX
///
- public static string StatusCodeClass2XX = "2XX";
+ public const string StatusCodeClass2XX = "2XX";
///
/// Status code: 200
///
- public static string StatusCode200 = "200";
+ public const string StatusCode200 = "200";
///
/// Status code: 201
///
- public static string StatusCode201 = "201";
+ public const string StatusCode201 = "201";
///
/// Status code: 204
///
- public static string StatusCode204 = "204";
+ public const string StatusCode204 = "204";
///
/// Status code: default
///
- public static string StatusCodeDefault = "default";
+ public const string StatusCodeDefault = "default";
///
/// Status code class: 4XX
///
- public static string StatusCodeClass4XX = "4XX";
+ public const string StatusCodeClass4XX = "4XX";
///
/// Status code class: 5XX
///
- public static string StatusCodeClass5XX = "5XX";
+ public const string StatusCodeClass5XX = "5XX";
///
/// Edm model error extension key.
///
- public static string xMsEdmModelError = "x-ms-edm-error-";
+ public const string xMsEdmModelError = "x-ms-edm-error-";
///
/// extension for toc (table of content) type
///
- public static string xMsTocType = "x-ms-docs-toc-type";
+ public const string xMsTocType = "x-ms-docs-toc-type";
///
/// extension for key type
///
- public static string xMsKeyType = "x-ms-docs-key-type";
+ public const string xMsKeyType = "x-ms-docs-key-type";
///
/// extension for operation type
///
- public static string xMsDosOperationType = "x-ms-docs-operation-type";
+ public const string xMsDosOperationType = "x-ms-docs-operation-type";
///
/// extension for group type
///
- public static string xMsDosGroupPath = "x-ms-docs-grouped-path";
+ public const string xMsDosGroupPath = "x-ms-docs-grouped-path";
///
/// extension for paging
///
- public static string xMsPageable = "x-ms-pageable";
+ public const string xMsPageable = "x-ms-pageable";
///
/// extension for discriminator value support
///
- public static string xMsDiscriminatorValue = "x-ms-discriminator-value";
+ public const string xMsDiscriminatorValue = "x-ms-discriminator-value";
///
/// extension for navigation property
///
- public static string xMsNavigationProperty = "x-ms-navigationProperty";
+ public const string xMsNavigationProperty = "x-ms-navigationProperty";
///
/// Name used for the OpenAPI referenced schema for OData Count operations responses.
///
- public static string DollarCountSchemaName = "ODataCountResponse";
+ public const string DollarCountSchemaName = "ODataCountResponse";
///
/// Suffix used for collection response schemas.
///
- public static string CollectionSchemaSuffix = "CollectionResponse";
+ public const string CollectionSchemaSuffix = "CollectionResponse";
///
/// Suffix used for the base collection pagination response schema and count response schemas.
///
- public static string BaseCollectionPaginationCountResponse = "BaseCollectionPaginationCountResponse";
+ public const string BaseCollectionPaginationCountResponse = "BaseCollectionPaginationCountResponse";
///
/// Suffix used for the base delta function response schemas.
///
- public static string BaseDeltaFunctionResponse = "BaseDeltaFunctionResponse";
+ public const string BaseDeltaFunctionResponse = "BaseDeltaFunctionResponse";
///
/// Name used for reference update.
///
- public static string ReferenceUpdateSchemaName = "ReferenceUpdate";
+ public const string ReferenceUpdateSchemaName = "ReferenceUpdate";
///
/// Name used for reference update.
///
- public static string ReferenceCreateSchemaName = "ReferenceCreate";
+ public const string ReferenceCreateSchemaName = "ReferenceCreate";
///
/// Name used for reference request POST body.
///
- public static string ReferencePostRequestBodyName = "refPostBody";
+ public const string ReferencePostRequestBodyName = "refPostBody";
///
/// Name used for reference request PUT body.
///
- public static string ReferencePutRequestBodyName = "refPutBody";
+ public const string ReferencePutRequestBodyName = "refPutBody";
///
/// Name used to reference INF, -INF and NaN
///
- public static string ReferenceNumericName = "ReferenceNumeric";
+ public const string ReferenceNumericName = "ReferenceNumeric";
///
/// The odata type name.
///
- public static string OdataType = "@odata.type";
+ public const string OdataType = "@odata.type";
///
/// The odata id.
///
- public static string OdataId = "@odata.id";
+ public const string OdataId = "@odata.id";
///
/// object type
///
- public static string ObjectType = "object";
+ public const string ObjectType = "object";
///
/// string type
///
- public static string StringType = "string";
-
- ///
- /// integer type
- ///
- [Obsolete("integer is not a valid OpenAPI type. Use number instead.")]
- public static string IntegerType = "integer";
+ public const string StringType = "string";
///
/// number type
///
- public static string NumberType = "number";
+ public const string NumberType = "number";
///
/// int64 format
///
- public static string Int64Format = "int64";
+ public const string Int64Format = "int64";
///
/// decimal format
///
- public static string DecimalFormat = "decimal";
+ public const string DecimalFormat = "decimal";
///
/// entity name
///
- public static string EntityName = "entity";
+ public const string EntityName = "entity";
///
/// count segment identifier
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs b/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
index 7bd5df68c..28b1d6bc4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs
@@ -10,6 +10,8 @@
using Microsoft.OData.Edm.Csdl;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
@@ -36,31 +38,15 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
OpenApiSchema schema = new()
{
- OneOf = new List()
+ OneOf = new List()
};
- OpenApiSchema baseTypeSchema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = schemaElement.FullName()
- }
- };
+ var baseTypeSchema = new OpenApiSchemaReference(schemaElement.FullName());
schema.OneOf.Add(baseTypeSchema);
foreach (IEdmSchemaElement derivedType in derivedTypes)
{
- OpenApiSchema derivedTypeSchema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = derivedType.FullName()
- }
- };
+ var derivedTypeSchema = new OpenApiSchemaReference(derivedType.FullName());
schema.OneOf.Add(derivedTypeSchema);
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
index 3eb561308..e2175058c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/OpenApiOperationExtensions.cs
@@ -4,6 +4,7 @@
// ------------------------------------------------------------
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.OData.Generator;
using System.Collections.Generic;
@@ -12,7 +13,7 @@ namespace Microsoft.OpenApi.OData.Common;
///
/// Extensions methods for the OpenApiOperation class.
///
-public static class OpenApiOperationExtensions
+internal static class OpenApiOperationExtensions
{
///
/// Adds a default response to the operation or 4XX/5XX responses for the errors depending on the settings.
@@ -22,7 +23,7 @@ public static class OpenApiOperationExtensions
/// The settings.
/// Optional: Whether to add a 204 no content response.
/// Optional: The OpenAPI schema of the response.
- public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false, OpenApiSchema schema = null)
+ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, bool addNoContent = false, IOpenApiSchema schema = null)
{
Utils.CheckArgumentNull(operation, nameof(operation));
Utils.CheckArgumentNull(settings, nameof(settings));
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
index d653de0ea..bbd253a0b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
@@ -12,6 +12,7 @@
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary;
@@ -152,13 +153,13 @@ internal static void AddCustomAttributesToExtensions(this IDictionary atrributesValueMap = GetCustomXMLAttributesValueMapping(context.Model, element, context.Settings.CustomXMLAttributesMapping);
+ Dictionary attributesValueMap = GetCustomXMLAttributesValueMapping(context.Model, element, context.Settings.CustomXMLAttributesMapping);
- if (atrributesValueMap?.Any() ?? false)
+ if (attributesValueMap?.Any() ?? false)
{
- foreach (var item in atrributesValueMap)
+ foreach (var item in attributesValueMap)
{
- extensions.TryAdd(item.Key, new OpenApiString(item.Value));
+ extensions.TryAdd(item.Key, new OpenApiAny(item.Value));
}
}
}
@@ -173,13 +174,13 @@ internal static void AddCustomAttributesToExtensions(this IDictionaryA dictionary of extension names mapped to the custom attribute values.
private static Dictionary GetCustomXMLAttributesValueMapping(IEdmModel model, IEdmElement element, Dictionary customXMLAttributesMapping)
{
- Dictionary atrributesValueMap = new();
+ Dictionary attributesValueMap = new();
if ((!customXMLAttributesMapping?.Any() ?? true) ||
model == null ||
element == null)
{
- return atrributesValueMap;
+ return attributesValueMap;
}
foreach (var item in customXMLAttributesMapping)
@@ -193,11 +194,11 @@ private static Dictionary GetCustomXMLAttributesValueMapping(IEd
if (!string.IsNullOrEmpty(attributeValue))
{
- atrributesValueMap.TryAdd(extensionName, attributeValue);
+ attributesValueMap.TryAdd(extensionName, attributeValue);
}
}
- return atrributesValueMap;
+ return attributesValueMap;
}
///
@@ -307,7 +308,7 @@ private static IEdmEntityType EntityTypeFromOperationSegment(this ODataSegment s
/// The value to be added.
/// true when the key and/or value are successfully added/updated to the dictionary;
/// false when the dictionary already contains the specified key, and nothing gets added.
- internal static bool TryAddPath(this IDictionary pathItems,
+ internal static bool TryAddPath(this IDictionary pathItems,
ODataContext context,
ODataPath path,
OpenApiPathItem pathItem)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
index b7dc53516..3ece9f1f6 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmModelExtensions.cs
@@ -43,7 +43,7 @@ public static bool IsUrlEscapeFunction(this IEdmModel model, IEdmOperation opera
/// The Edm model.
/// The specified function
/// true if the specified operation is UrlEscape function; otherwise, false.
- public static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction function)
+ private static bool IsUrlEscapeFunction(this IEdmModel model, IEdmFunction function)
{
Utils.CheckArgumentNull(model, nameof(model));
Utils.CheckArgumentNull(function, nameof(function));
@@ -157,9 +157,9 @@ public static bool IsOperationOverload(this IEdmModel model, IEdmOperation opera
Utils.CheckArgumentNull(operation, nameof(operation));
return model.GetAllElements().OfType()
- .Where(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
+ .Count(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
o.Parameters.First().Type.Definition.FullTypeName() == operation.Parameters.First().Type.Definition.FullTypeName()
- ).Count() > 1;
+ ) > 1;
}
///
@@ -180,7 +180,7 @@ public static bool OperationTargetsMultiplePaths(this IEdmModel model, IEdmOpera
return model.EntityContainer.EntitySets().Select(static x => x.EntityType)
.Concat(model.EntityContainer.Singletons().Select(static x => x.EntityType))
- .Where(x => x.FullName().Equals(bindingParameterType.FullName(), StringComparison.OrdinalIgnoreCase)).Count() > 1;
+ .Count(x => x.FullName().Equals(bindingParameterType.FullName(), StringComparison.OrdinalIgnoreCase)) > 1;
}
///
@@ -200,7 +200,7 @@ public static bool IsOperationImportOverload(this IEdmModel model, IEdmOperation
}
return model.EntityContainer.OperationImports()
- .Where(o => o.Operation.IsBound == operationImport.Operation.IsBound && o.Name == operationImport.Name).Count() > 1;
+ .Count(o => o.Operation.IsBound == operationImport.Operation.IsBound && o.Name == operationImport.Name) > 1;
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
index e7fab01a2..06df4f25f 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs
@@ -3,10 +3,12 @@
// 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.Any;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Generator;
@@ -23,7 +25,7 @@ namespace Microsoft.OpenApi.OData.Edm
internal class ODataContext
{
private IEnumerable _allPaths;
- private IODataPathProvider _pathProvider;
+ private readonly IODataPathProvider _pathProvider;
///
/// Initializes a new instance of class.
@@ -48,8 +50,8 @@ public ODataContext(IEdmModel model, OpenApiConvertSettings settings)
visitor.Visit(model);
IsSpatialTypeUsed = visitor.IsSpatialTypeUsed;
- OperationHanderProvider = new OperationHandlerProvider();
- PathItemHanderProvider = new PathItemHandlerProvider();
+ OperationHandlerProvider = new CachedOperationHandlerProvider(new OperationHandlerProvider());
+ PathItemHandlerProvider = new CachedPathItemHandlerProvider(new PathItemHandlerProvider());
// If no path provider, use the default path provider.
_pathProvider = settings.PathProvider ?? new ODataPathProvider();
@@ -76,12 +78,12 @@ public ODataContext(IEdmModel model, OpenApiConvertSettings settings)
///
/// Gets the path item handler provider.
///
- public IPathItemHandlerProvider PathItemHanderProvider { get; }
+ public IPathItemHandlerProvider PathItemHandlerProvider { get; }
///
/// Gets the operation handler provider.
///
- public IOperationHandlerProvider OperationHanderProvider { get; }
+ public IOperationHandlerProvider OperationHandlerProvider { get; }
///
/// Gets the Edm model.
@@ -139,14 +141,11 @@ public IEnumerable AllPaths
/// Append tag.
///
/// The tag item.
- public void AppendTag(OpenApiTag tagItem)
+ internal void AppendTag(OpenApiTag tagItem)
{
- if (Tags == null)
- {
- Tags = new List();
- }
+ Tags ??= [];
- if (Tags.Any(c => c.Name == tagItem.Name))
+ if (FindTagByName(tagItem.Name) is not null)
{
return;
}
@@ -154,6 +153,43 @@ public void AppendTag(OpenApiTag tagItem)
Tags.Add(tagItem);
}
+ ///
+ /// Find tag by name.
+ ///
+ /// The name to lookup the tag.
+ ///
+ internal OpenApiTag FindTagByName(string name)
+ {
+ Utils.CheckArgumentNullOrEmpty(name, nameof(name));
+ return Tags?.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, name));
+ }
+
+ ///
+ /// Sets the extension for the existing tag, or create a new tag with the extension.
+ ///
+ /// The tag name to lookup.
+ /// The extension name.
+ /// The extension value to set.
+ /// The tag default value factory.
+ internal void AddExtensionToTag(string tagName, string extensionName, OpenApiAny extensionValue, Func initialValueFactory)
+ {
+ Utils.CheckArgumentNullOrEmpty(tagName, nameof(tagName));
+ Utils.CheckArgumentNullOrEmpty(extensionName, nameof(extensionName));
+ Utils.CheckArgumentNull(extensionValue, nameof(extensionValue));
+ Utils.CheckArgumentNull(initialValueFactory, nameof(initialValueFactory));
+
+ if (FindTagByName(tagName) is {} foundTag)
+ {
+ foundTag.Extensions.TryAdd(extensionName, extensionValue);
+ }
+ else
+ {
+ var tag = initialValueFactory();
+ tag.Extensions.TryAdd(extensionName, extensionValue);
+ AppendTag(tag);
+ }
+ }
+
///
/// Gets all OData paths
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
index 6a7e660e1..47da7fd4f 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs
@@ -43,7 +43,7 @@ public ODataTypeCastSegment(IEdmStructuredType structuredType, IEdmModel model)
///
public override IEnumerable GetAnnotables()
{
- return new IEdmVocabularyAnnotatable[] { StructuredType as IEdmVocabularyAnnotatable };
+ return [StructuredType as IEdmVocabularyAnnotatable];
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
index 60fab5ca6..5fe3f4b07 100644
--- a/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/EdmModelOpenApiExtensions.cs
@@ -3,7 +3,6 @@
// 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.Validation;
using Microsoft.OpenApi.Any;
@@ -48,7 +47,7 @@ public static OpenApiDocument ConvertToOpenApi(this IEdmModel model, OpenApiConv
int index = 1;
foreach (var error in errors)
{
- document.Extensions.Add(Constants.xMsEdmModelError + index++, new OpenApiString(error.ToString()));
+ document.Extensions.Add(Constants.xMsEdmModelError + index++, new OpenApiAny(error.ToString()));
}
return document;
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
index 14ff0c218..64fe4417a 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiComponentsGenerator.cs
@@ -20,47 +20,21 @@ internal static class OpenApiComponentsGenerator
/// It holds maps of reusable schemas describing message bodies, operation parameters, and responses.
///
/// The OData to Open API context.
- /// The created object.
- public static OpenApiComponents CreateComponents(this ODataContext context)
+ /// The Open API document.
+ public static void AddComponentsToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
-
- // "components": {
- // "schemas": …,
- // "parameters": …,
- // "responses": …,
- // "requestBodies": …
- // }
- return new OpenApiComponents
- {
- // The value of schemas is a map of Schema Objects.
- // 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.
- Schemas = context.CreateSchemas(),
-
- // The value of parameters is a map of Parameter Objects.
- // It allows defining query options and headers that can be reused across operations of the service.
- Parameters = context.CreateParameters(),
-
- // The value of responses is a map of Response Objects.
- // It allows defining responses that can be reused across operations of the service.
- Responses = context.CreateResponses(),
-
- // The value of requestBodies is a map of RequestBody Objects.
- // It allows refining request bodies that can be reused across operations of the service.
- RequestBodies = context.CreateRequestBodies(),
-
- Examples = context.CreateExamples(),
-
- SecuritySchemes = context.CreateSecuritySchemes(),
-
- // Make others as null.
- Links = null,
-
- Callbacks = null,
-
- Extensions = null
- };
+ Utils.CheckArgumentNull(document, nameof(document));
+
+ context.AddSchemasToDocument(document);
+ context.AddParametersToDocument(document);
+ context.AddResponsesToDocument(document);
+ context.AddRequestBodiesToDocument(document);
+ context.AddExamplesToDocument(document);
+ context.AddSecuritySchemesToDocument(document);
+ document.Components.Links = null;
+ document.Components.Callbacks = null;
+ document.Components.Extensions = null;
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs
index 4660cfb3c..b1e393fc0 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs
@@ -32,24 +32,23 @@ public static OpenApiDocument CreateDocument(this ODataContext context)
// "paths": …,
// "components": …
// }
- OpenApiDocument doc = new OpenApiDocument
+ OpenApiDocument doc = new()
{
Info = context.CreateInfo(),
Servers = context.CreateServers(),
- // Tags = context.CreateTags(),
-
- Paths = context.CreatePaths(),
-
- Components = context.CreateComponents(),
-
SecurityRequirements = null,
- ExternalDocs = null
+ ExternalDocs = null,
};
- doc.Tags = context.CreateTags();
+ context.AddComponentsToDocument(doc);
+ context.AddPathsToDocument(doc);
+ doc.Tags = context.CreateTags(); // order matters so the operation generators have populated the tags
+ doc.RegisterComponents();
+ doc.SetReferenceHostDocument();
+
return doc;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs
index 1144abf3e..4982b9ba9 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs
@@ -7,12 +7,14 @@
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 Microsoft.OpenApi.OData.Common;
+using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -21,13 +23,22 @@ namespace Microsoft.OpenApi.OData.Generator
///
internal static class OpenApiEdmTypeSchemaGenerator
{
+ ///
+ /// Create a for a when producing an OpenAPI parameter.
+ ///
+ /// The OData context.
+ /// The Edm type reference.
+ /// The created .
+ public static IOpenApiSchema CreateEdmTypeSchemaForParameter(this ODataContext context, IEdmTypeReference edmTypeReference)
+ => CreateEdmTypeSchema(context, edmTypeReference, true);
///
/// Create a for a .
///
/// The OData context.
/// The Edm type reference.
+ /// Whether the schema is for a parameter.
/// The created .
- public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmTypeReference edmTypeReference)
+ public static IOpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmTypeReference edmTypeReference, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(edmTypeReference, nameof(edmTypeReference));
@@ -39,14 +50,13 @@ public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmT
case EdmTypeKind.Collection:
IEdmTypeReference typeRef = edmTypeReference.AsCollection().ElementType();
- OpenApiSchema schema;
- schema = typeRef.TypeKind() == EdmTypeKind.Complex || typeRef.TypeKind() == EdmTypeKind.Entity
+ var schema = typeRef.TypeKind() == EdmTypeKind.Complex || typeRef.TypeKind() == EdmTypeKind.Entity
? context.CreateStructuredTypeSchema(typeRef.AsStructured(), true)
- : context.CreateEdmTypeSchema(typeRef);
+ : context.CreateEdmTypeSchema(typeRef, schemaForParameter);
return new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = schema
};
@@ -64,10 +74,10 @@ public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmT
// represented as Schema Objects that are JSON References to definitions in the Definitions Object
case EdmTypeKind.Primitive:
IEdmPrimitiveTypeReference primitiveTypeReference = (IEdmPrimitiveTypeReference)edmTypeReference;
- return context.CreateSchema(primitiveTypeReference);
+ return context.CreateSchema(primitiveTypeReference, schemaForParameter);
case EdmTypeKind.TypeDefinition:
- return context.CreateSchema(((IEdmTypeDefinitionReference)edmTypeReference).TypeDefinition().UnderlyingType);
+ return context.CreateSchema(((IEdmTypeDefinitionReference)edmTypeReference).TypeDefinition().UnderlyingType, schemaForParameter);
case EdmTypeKind.EntityReference:
return context.CreateTypeDefinitionSchema(edmTypeReference.AsTypeDefinition());
@@ -82,24 +92,25 @@ public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmT
}
///
- /// Create a for a .
+ /// Create a for a .
///
/// The OData context.
/// The Edm primitive reference.
- /// The created .
- public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveTypeReference primitiveType)
+ /// Whether the schema is for a parameter.
+ /// The created .
+ public static IOpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveTypeReference primitiveType, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
- OpenApiSchema schema = context.CreateSchema(primitiveType.PrimitiveDefinition());
- if (schema != null)
+ var schema = context.CreateSchema(primitiveType.PrimitiveDefinition(), schemaForParameter);
+ if (schema is OpenApiSchema openApiSchema)
{
switch(primitiveType.PrimitiveKind())
{
case EdmPrimitiveTypeKind.Binary: // binary
IEdmBinaryTypeReference binaryTypeReference = (IEdmBinaryTypeReference)primitiveType;
- schema.MaxLength = binaryTypeReference.MaxLength;
+ openApiSchema.MaxLength = binaryTypeReference.MaxLength;
break;
case EdmPrimitiveTypeKind.Decimal: // decimal
@@ -111,30 +122,33 @@ public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiv
// The precision is represented with the maximum and minimum keywords and a value of ±(10^ (precision - scale) - 10^ scale).
double tmp = Math.Pow(10, decimalTypeReference.Precision.Value - decimalTypeReference.Scale.Value)
- Math.Pow(10, -decimalTypeReference.Scale.Value);
- schema.Minimum = (decimal?)(tmp * -1.0);
- schema.Maximum = (decimal?)(tmp);
+ openApiSchema.Minimum = (decimal?)(tmp * -1.0);
+ openApiSchema.Maximum = (decimal?)(tmp);
}
else
{
// If the scale facet has a numeric value, and ±(10^precision - 1) if the scale is variable
double tmp = Math.Pow(10, decimalTypeReference.Precision.Value) - 1;
- schema.Minimum = (decimal?)(tmp * -1.0);
- schema.Maximum = (decimal?)(tmp);
+ openApiSchema.Minimum = (decimal?)(tmp * -1.0);
+ openApiSchema.Maximum = (decimal?)(tmp);
}
}
// The scale of properties of type Edm.Decimal are represented with the OpenAPI Specification keyword multipleOf and a value of 10 ^ -scale
- schema.MultipleOf = decimalTypeReference.Scale == null ? null : (decimal?)(Math.Pow(10, decimalTypeReference.Scale.Value * -1));
+ openApiSchema.MultipleOf = decimalTypeReference.Scale == null ? null : (decimal?)(Math.Pow(10, decimalTypeReference.Scale.Value * -1));
break;
case EdmPrimitiveTypeKind.String: // string
IEdmStringTypeReference stringTypeReference = (IEdmStringTypeReference)primitiveType;
- schema.MaxLength = stringTypeReference.MaxLength;
+ openApiSchema.MaxLength = stringTypeReference.MaxLength;
break;
}
// Nullable properties are marked with the keyword nullable and a value of true.
// nullable cannot be true when type is empty, often common in anyof/allOf since individual entries are nullable
- schema.Nullable = !string.IsNullOrEmpty(schema.Type) && primitiveType.IsNullable;
+ if (!string.IsNullOrEmpty(schema.Type.ToIdentifier()) && primitiveType.IsNullable)
+ {
+ openApiSchema.Type |= JsonSchemaType.Null;
+ }
}
return schema;
@@ -145,8 +159,9 @@ public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiv
///
/// The OData context.
/// The Edm primitive type.
+ /// Whether the schema is for a parameter.
/// The created .
- public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveType primitiveType)
+ public static IOpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveType primitiveType, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
@@ -159,261 +174,152 @@ public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiv
AnyOf = null
};
+ var emitIEEECompatibleTypes = context.Settings.IEEE754Compatible && (context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0 || !schemaForParameter);
+ var emitV2CompatibleParameterTypes = context.Settings.OpenApiSpecVersion == OpenApiSpecVersion.OpenApi2_0 && schemaForParameter;
+
switch (primitiveType.PrimitiveKind)
{
case EdmPrimitiveTypeKind.Binary: // binary
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "base64url";
break;
case EdmPrimitiveTypeKind.Boolean: // boolean
- schema.Type = "boolean";
- schema.Default = new OpenApiBoolean(false);
+ schema.Type = JsonSchemaType.Boolean;
+ schema.Default = false;
break;
case EdmPrimitiveTypeKind.Byte: // byte
- schema.Type = Constants.NumberType;
+ schema.Type = JsonSchemaType.Number;
schema.Format = "uint8";
break;
case EdmPrimitiveTypeKind.DateTimeOffset: // datetime offset
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "date-time";
schema.Pattern = "^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?(Z|[+-][0-9][0-9]:[0-9][0-9])$";
break;
- case EdmPrimitiveTypeKind.Decimal: // decimal
- if (context.Settings.IEEE754Compatible)
- {
- schema.OneOf = new List
- {
- new OpenApiSchema { Type = Constants.NumberType, Format = Constants.DecimalFormat, Nullable = true },
- new OpenApiSchema { Type = Constants.StringType, Nullable = true },
- };
- }
- else
- {
- schema.Type = Constants.NumberType;
- schema.Format = Constants.DecimalFormat;
- }
+ case EdmPrimitiveTypeKind.Decimal when emitIEEECompatibleTypes: // decimal
+ schema.OneOf =
+ [
+ new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = Constants.DecimalFormat },
+ new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null },
+ ];
break;
- case EdmPrimitiveTypeKind.Double: // double
- schema.OneOf = new List
- {
- new OpenApiSchema { Type = Constants.NumberType, Format = "double", Nullable = true },
- new OpenApiSchema { Type = Constants.StringType, Nullable = true },
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceNumericName
- }
- }
- };
+ case EdmPrimitiveTypeKind.Decimal when !emitIEEECompatibleTypes: // decimal
+ schema.Type = JsonSchemaType.Number;
+ schema.Format = Constants.DecimalFormat;
break;
- case EdmPrimitiveTypeKind.Single: // single
- schema.OneOf = new List
- {
- new OpenApiSchema { Type = Constants.NumberType, Format = "float", Nullable = true },
- new OpenApiSchema { Type = Constants.StringType, Nullable = true },
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceNumericName
- }
- }
- };
+ case EdmPrimitiveTypeKind.Double when emitV2CompatibleParameterTypes: // double
+ schema.Type = JsonSchemaType.Number | JsonSchemaType.Null;
+ schema.Format = "double";
+ break;
+ case EdmPrimitiveTypeKind.Double when !emitV2CompatibleParameterTypes: // double
+ schema.OneOf =
+ [
+ new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double" },
+ new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null },
+ new OpenApiSchemaReference(Constants.ReferenceNumericName)
+ ];
+ break;
+ case EdmPrimitiveTypeKind.Single when emitV2CompatibleParameterTypes: // single
+ schema.Type = JsonSchemaType.Number | JsonSchemaType.Null;
+ schema.Format = "float";
+ break;
+ case EdmPrimitiveTypeKind.Single when !emitV2CompatibleParameterTypes: // single
+ schema.OneOf =
+ [
+ new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "float"},
+ new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null},
+ new OpenApiSchemaReference(Constants.ReferenceNumericName)
+ ];
break;
case EdmPrimitiveTypeKind.Guid: // guid
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "uuid";
schema.Pattern = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
break;
case EdmPrimitiveTypeKind.Int16:
- schema.Type = Constants.NumberType;
+ schema.Type = JsonSchemaType.Number;
schema.Format = "int16";
schema.Minimum = Int16.MinValue; // -32768
schema.Maximum = Int16.MaxValue; // 32767
break;
case EdmPrimitiveTypeKind.Int32:
- schema.Type = Constants.NumberType;
+ schema.Type = JsonSchemaType.Number;
schema.Format = "int32";
schema.Minimum = Int32.MinValue; // -2147483648
schema.Maximum = Int32.MaxValue; // 2147483647
break;
- case EdmPrimitiveTypeKind.Int64:
- if (context.Settings.IEEE754Compatible)
- {
- schema.OneOf = new List
- {
- new OpenApiSchema { Type = Constants.NumberType, Format = Constants.Int64Format, Nullable = true },
- new OpenApiSchema { Type = Constants.StringType, Nullable = true }
- };
- }
- else
- {
- schema.Type = Constants.NumberType;
- schema.Format = Constants.Int64Format;
- }
+ case EdmPrimitiveTypeKind.Int64 when emitIEEECompatibleTypes:
+ schema.OneOf =
+ [
+ new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = Constants.Int64Format},
+ new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null }
+ ];
+ break;
+ case EdmPrimitiveTypeKind.Int64 when !emitIEEECompatibleTypes:
+ schema.Type = JsonSchemaType.Number;
+ schema.Format = Constants.Int64Format;
break;
case EdmPrimitiveTypeKind.SByte:
- schema.Type = Constants.NumberType;
+ schema.Type = JsonSchemaType.Number;
schema.Format = "int8";
schema.Minimum = SByte.MinValue; // -128
schema.Maximum = SByte.MaxValue; // 127
break;
case EdmPrimitiveTypeKind.String: // string
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
break;
case EdmPrimitiveTypeKind.Stream: // stream
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "base64url";
break;
case EdmPrimitiveTypeKind.Duration: // duration
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "duration";
schema.Pattern = "^-?P([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+([.][0-9]+)?S)?)?$";
break;
case EdmPrimitiveTypeKind.Date:
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "date";
schema.Pattern = "^[0-9]{4,}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$";
break;
case EdmPrimitiveTypeKind.TimeOfDay:
- schema.Type = Constants.StringType;
+ schema.Type = JsonSchemaType.String;
schema.Format = "time";
schema.Pattern = "^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]([.][0-9]{1,12})?$";
break;
case EdmPrimitiveTypeKind.Geography:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.Geography"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.Geography");
case EdmPrimitiveTypeKind.GeographyPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyPoint");
case EdmPrimitiveTypeKind.GeographyLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyLineString");
case EdmPrimitiveTypeKind.GeographyPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyPolygon");
case EdmPrimitiveTypeKind.GeographyCollection:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyCollection"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyCollection");
case EdmPrimitiveTypeKind.GeographyMultiPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiPolygon");
case EdmPrimitiveTypeKind.GeographyMultiLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiLineString");
case EdmPrimitiveTypeKind.GeographyMultiPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiPoint");
case EdmPrimitiveTypeKind.Geometry: // Geometry
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.Geometry"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.Geometry");
case EdmPrimitiveTypeKind.GeometryPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryPoint");
case EdmPrimitiveTypeKind.GeometryLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryLineString");
case EdmPrimitiveTypeKind.GeometryPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryPolygon");
case EdmPrimitiveTypeKind.GeometryCollection:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryCollection"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryCollection");
case EdmPrimitiveTypeKind.GeometryMultiPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiPolygon");
case EdmPrimitiveTypeKind.GeometryMultiLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiLineString");
case EdmPrimitiveTypeKind.GeometryMultiPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiPoint");
case EdmPrimitiveTypeKind.None:
default:
@@ -423,57 +329,36 @@ public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiv
return schema;
}
- private static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdmEnumTypeReference typeReference)
+ private static IOpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdmEnumTypeReference typeReference)
{
Debug.Assert(context != null);
Debug.Assert(typeReference != null);
- OpenApiSchema schema = new OpenApiSchema();
- schema.Reference = null;
if (typeReference.IsNullable && context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
{
- schema.AnyOf = new List
- {
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
+ return new OpenApiSchema {
+ AnyOf =
+ [
+ new OpenApiSchemaReference(typeReference.Definition.FullTypeName()),
+ new OpenApiSchema
{
- Type = ReferenceType.Schema,
- Id = typeReference.Definition.FullTypeName()
+ Type = JsonSchemaType.Null,
}
- },
- new OpenApiSchema
- {
- Type = "object",
- Nullable = true
- }
+ ]
};
}
else
{
- schema.Type = null;
- schema.AnyOf = null;
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = typeReference.Definition.FullTypeName()
- };
- schema.UnresolvedReference = true;
- schema.Nullable = typeReference.IsNullable;
+ return new OpenApiSchemaReference(typeReference.Definition.FullTypeName());
}
-
- return schema;
}
- private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredTypeReference typeReference, bool isTypeCollection = false)
+ private static IOpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredTypeReference typeReference, bool isTypeCollection = false)
{
Debug.Assert(context != null);
Debug.Assert(typeReference != null);
- OpenApiSchema schema = new OpenApiSchema();
-
// AnyOf will only be valid openApi for version 3
// otherwise the reference should be set directly
// as per OASIS documentation for openApi version 2
@@ -481,84 +366,45 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
if (typeReference.IsNullable && !isTypeCollection &&
(context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0))
{
- schema.Reference = null;
- schema.AnyOf = new List
- {
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
+ return new OpenApiSchema {
+ AnyOf =
+ [
+ new OpenApiSchemaReference(typeReference.Definition.FullTypeName()),
+ new OpenApiSchema
{
- Type = ReferenceType.Schema,
- Id = typeReference.Definition.FullTypeName()
+ Type = JsonSchemaType.Null,
}
- },
- new OpenApiSchema
- {
- Type = "object",
- Nullable = true
- }
+ ]
};
}
else
{
- schema.Type = null;
- schema.AnyOf = null;
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = typeReference.Definition.FullTypeName()
- };
- schema.UnresolvedReference = true;
- schema.Nullable = typeReference.IsNullable;
+ return new OpenApiSchemaReference(typeReference.Definition.FullTypeName());
}
-
- return schema;
}
- private static OpenApiSchema CreateTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinitionReference reference)
+ private static IOpenApiSchema CreateTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinitionReference reference)
{
Debug.Assert(context != null);
Debug.Assert(reference != null);
- OpenApiSchema schema = new OpenApiSchema();
- schema.Reference = null;
-
if (reference.IsNullable && context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
{
- schema.AnyOf = new List
- {
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
+ return new OpenApiSchema {
+ AnyOf =
+ [
+ new OpenApiSchemaReference(reference.Definition.FullTypeName()),
+ new OpenApiSchema
{
- Type = ReferenceType.Schema,
- Id = reference.Definition.FullTypeName()
+ Type = JsonSchemaType.Null,
}
- },
- new OpenApiSchema
- {
- Type = "object",
- Nullable = true
- }
+ ]
};
}
else
{
- schema.Type = null;
- schema.AnyOf = null;
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = reference.Definition.FullTypeName()
- };
- schema.UnresolvedReference = true;
- schema.Nullable = reference.IsNullable;
- }
-
-
- return schema;
+ return new OpenApiSchemaReference(reference.Definition.FullTypeName());
+ }
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs
index beeaa1d1d..c6f954ded 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs
@@ -11,6 +11,8 @@
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.MicrosoftExtensions;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -31,12 +33,12 @@ internal static class OpenApiErrorSchemaGenerator
///
/// The OData to Open API context.
/// The string/schema dictionary.
- public static IDictionary CreateODataErrorSchemas(this ODataContext context)
+ public static IDictionary CreateODataErrorSchemas(this ODataContext context)
{
Utils.CheckArgumentNull(context, nameof(context));
var rootNamespaceName = context.GetErrorNamespaceName();
- return new Dictionary()
+ return new Dictionary()
{
{ $"{rootNamespaceName}{ODataErrorClassName}", CreateErrorSchema(rootNamespaceName) },
{ $"{rootNamespaceName}{MainErrorClassName}", CreateErrorMainSchema(rootNamespaceName) },
@@ -67,24 +69,16 @@ public static OpenApiSchema CreateErrorSchema(string rootNamespaceName)
{
return new OpenApiSchema
{
- Type = "object",
+ Type = JsonSchemaType.Object,
Required = new HashSet
{
"error"
},
- Properties = new Dictionary
+ Properties = new Dictionary
{
{
"error",
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{rootNamespaceName}{MainErrorClassName}"
- }
- }
+ new OpenApiSchemaReference($"{rootNamespaceName}{MainErrorClassName}")
}
}
};
@@ -96,7 +90,7 @@ public static OpenApiSchema CreateErrorSchema(string rootNamespaceName)
///
/// The OData to Open API context.
/// The inner error schema definition.
- public static OpenApiSchema CreateInnerErrorSchema(ODataContext context)
+ public static IOpenApiSchema CreateInnerErrorSchema(ODataContext context)
{
Utils.CheckArgumentNull(context, nameof(context));
@@ -110,7 +104,7 @@ public static OpenApiSchema CreateInnerErrorSchema(ODataContext context)
return new OpenApiSchema
{
- Type = "object",
+ Type = JsonSchemaType.Object,
Description = "The structure of this object is service-specific"
};
}
@@ -124,50 +118,34 @@ public static OpenApiSchema CreateErrorMainSchema(string rootNamespaceName)
{
return new OpenApiSchema
{
- Type = "object",
+ Type = JsonSchemaType.Object,
Required = new HashSet
{
"code", "message"
},
- Properties = new Dictionary
+ Properties = new Dictionary
{
{
- "code", new OpenApiSchema { Type = "string", Nullable = false }
+ "code", new OpenApiSchema { Type = JsonSchemaType.String }
},
{
- "message", new OpenApiSchema { Type = "string", Nullable = false, Extensions = new Dictionary
+ "message", new OpenApiSchema { Type = JsonSchemaType.String, Extensions = new Dictionary
{ { OpenApiPrimaryErrorMessageExtension.Name, new OpenApiPrimaryErrorMessageExtension { IsPrimaryErrorMessage = true } } } }
},
{
- "target", new OpenApiSchema { Type = "string", Nullable = true }
+ "target", new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null }
},
{
"details",
new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{rootNamespaceName}{ErrorDetailsClassName}"
- }
- }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference($"{rootNamespaceName}{ErrorDetailsClassName}")
}
},
{
"innerError",
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{rootNamespaceName}{InnerErrorClassName}"
- }
- }
+ new OpenApiSchemaReference($"{rootNamespaceName}{InnerErrorClassName}")
}
}
};
@@ -181,21 +159,21 @@ public static OpenApiSchema CreateErrorDetailSchema()
{
return new OpenApiSchema
{
- Type = "object",
+ Type = JsonSchemaType.Object,
Required = new HashSet
{
"code", "message"
},
- Properties = new Dictionary
+ Properties = new Dictionary
{
{
- "code", new OpenApiSchema { Type = "string", Nullable = false, }
+ "code", new OpenApiSchema { Type = JsonSchemaType.String, }
},
{
- "message", new OpenApiSchema { Type = "string", Nullable = false, }
+ "message", new OpenApiSchema { Type = JsonSchemaType.String, }
},
{
- "target", new OpenApiSchema { Type = "string", Nullable = true, }
+ "target", new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null, }
}
}
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
index bdba738c0..7f3f140da 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiExampleGenerator.cs
@@ -8,8 +8,6 @@
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;
@@ -25,37 +23,28 @@ internal static class OpenApiExampleGenerator
/// Create the dictionary of object.
///
/// The OData to Open API context.
- /// The created dictionary.
- public static IDictionary CreateExamples(this ODataContext context)
+ /// The Open API document.
+ public static void AddExamplesToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
- IDictionary examples = new Dictionary();
// 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.
// Ideally this would be driven off the types used in the paths, but in practice, it is simply
// all of the types present in the model.
- IEnumerable elements = context.Model.GetAllElements();
+ var elements = context.Model.GetAllElements()
+ .Where(static x => x.SchemaElementKind is EdmSchemaElementKind.TypeDefinition)
+ .OfType();
foreach (var element in elements)
{
- switch (element.SchemaElementKind)
+ if (context.CreateExample(element) is OpenApiExample example)
{
- case EdmSchemaElementKind.TypeDefinition: // Type definition
- {
- IEdmType reference = (IEdmType)element;
- OpenApiExample example = context.CreateExample(reference);
- if (example != null)
- {
- examples.Add(reference.FullTypeName(), example);
- }
- }
- break;
+ document.AddComponent(element.FullTypeName(), example);
}
}
-
- return examples;
}
private static OpenApiExample CreateExample(this ODataContext context, IEdmType edmType)
@@ -63,129 +52,15 @@ private static OpenApiExample CreateExample(this ODataContext context, IEdmType
Debug.Assert(context != null);
Debug.Assert(edmType != null);
- switch (edmType.TypeKind)
+ return edmType.TypeKind switch
{
- 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)
+ // complex type
+ EdmTypeKind.Complex or EdmTypeKind.Entity when edmType is IEdmStructuredType edmStructuredType => new()
{
- 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.IsBinary())
- {
- // return new OpenApiBinary(new byte[] { 0x00 }); issue on binary writing
- return new OpenApiString(Convert.ToBase64String(new byte[] { 0x00 }));
- }
- else if (edmTypeReference.IsBoolean())
- {
- return new OpenApiBoolean(true);
- }
- else if (edmTypeReference.IsByte())
- {
- return new OpenApiByte(0x00);
- }
- else if (edmTypeReference.IsDate())
- {
- return new OpenApiDate(DateTime.MinValue);
- }
- else if (edmTypeReference.IsDateTimeOffset())
- {
- return new OpenApiDateTime(DateTimeOffset.MinValue);
- }
- else if (edmTypeReference.IsDecimal() || edmTypeReference.IsDouble())
- {
- return new OpenApiDouble(0D);
- }
- else if (edmTypeReference.IsFloating())
- {
- return new OpenApiFloat(0F);
- }
- else if (edmTypeReference.IsGuid())
- {
- return new OpenApiString(Guid.Empty.ToString());
- }
- else if (edmTypeReference.IsInt16() || edmTypeReference.IsInt32())
- {
- return new OpenApiInteger(0);
- }
- else if (edmTypeReference.IsInt64())
- {
- return new OpenApiLong(0L);
- }
- 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.TypeDefinition:
- var typedef = edmTypeReference.AsTypeDefinition().TypeDefinition();
- return GetTypeNameForExample(new EdmPrimitiveTypeReference(typedef.UnderlyingType, edmTypeReference.IsNullable));
-
- case EdmTypeKind.Untyped:
- return new OpenApiObject();
-
- case EdmTypeKind.EntityReference:
- default:
- throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind());
- }
+ Value = OpenApiSchemaGenerator.CreateStructuredTypePropertiesExample(context, edmStructuredType),
+ },
+ _ => null,
+ };
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
index 3aa432e30..085cb5bb8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiInfoGenerator.cs
@@ -7,6 +7,7 @@
using System.Diagnostics;
using System.Linq;
using System.Reflection;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
@@ -109,11 +110,11 @@ private static Dictionary GetExtensions(this ODataCon
{
{
"x-ms-generated-by",
- new OpenApiObject
+ new OpenApiAny(new JsonObject
{
- { "toolName", new OpenApiString("Microsoft.OpenApi.OData") },
- { "toolVersion", new OpenApiString(Assembly.GetExecutingAssembly().GetName().Version.ToString()) }
- }
+ { "toolName", "Microsoft.OpenApi.OData" },
+ { "toolVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString() }
+ })
}
};
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
index 1f92f02a8..5fb7804ea 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiLinkGenerator.cs
@@ -7,9 +7,9 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.OData.Edm;
using System.Linq;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -29,9 +29,9 @@ internal static class OpenApiLinkGenerator
/// "Optional: The list of parameters of the incoming operation.
/// Optional: The operation id of the source of the NavigationProperty object.
/// The created dictionary of object.
- public static IDictionary CreateLinks(this ODataContext context,
+ public static IDictionary CreateLinks(this ODataContext context,
IEdmEntityType entityType, string entityName, string entityKind, ODataPath path,
- IList parameters = null, string navPropOperationId = null)
+ IList parameters = null, string navPropOperationId = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(entityType, nameof(entityType));
@@ -54,7 +54,7 @@ public static IDictionary CreateLinks(this ODataContext con
}
}
- Dictionary links = new();
+ Dictionary links = new();
bool lastSegmentIsColNavProp = (path.LastSegment as ODataNavigationPropertySegment)?.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many;
// Valid only for non collection-valued navigation properties
@@ -97,7 +97,7 @@ public static IDictionary CreateLinks(this ODataContext con
{
link.Parameters[pathKeyName] = new RuntimeExpressionAnyWrapper
{
- Any = new OpenApiString("$request.path." + pathKeyName)
+ Any = "$request.path." + pathKeyName
};
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
index eaceb8700..eb3c7e3f8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs
@@ -6,7 +6,6 @@
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.OData.Edm.Vocabularies;
@@ -14,6 +13,10 @@
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
using System.Diagnostics;
using System;
+using System.Text.Json.Nodes;
+using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -27,21 +30,19 @@ internal static class OpenApiParameterGenerator
/// Create a map of object.
///
/// The OData context.
- /// The created map of object.
- public static IDictionary CreateParameters(this ODataContext context)
+ /// The Open API document.
+ public static void AddParametersToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
// 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.
- return new Dictionary
- {
- { "top", CreateTop(context.Settings.TopExample) },
- { "skip", CreateSkip() },
- { "count", CreateCount() },
- { "filter", CreateFilter() },
- { "search", CreateSearch() },
- };
+ document.AddComponent("top", CreateTop(context.Settings.TopExample));
+ document.AddComponent("skip", CreateSkip());
+ document.AddComponent("count", CreateCount());
+ document.AddComponent("filter", CreateFilter());
+ document.AddComponent("search", CreateSearch());
}
///
@@ -50,7 +51,7 @@ public static IDictionary CreateParameters(this ODataC
/// The OData context.
/// The Edm function import.
/// The created list of .
- public static IList CreateParameters(this ODataContext context, IEdmFunctionImport functionImport)
+ public static IList CreateParameters(this ODataContext context, IEdmFunctionImport functionImport)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(functionImport, nameof(functionImport));
@@ -65,23 +66,20 @@ public static IList CreateParameters(this ODataContext context
/// The Edm function.
/// The parameter name mapping.
/// The created list of .
- public static IList CreateParameters(this ODataContext context, IEdmFunction function,
+ public static IList CreateParameters(this ODataContext context, IEdmFunction function,
IDictionary parameterNameMapping = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(function, nameof(function));
- IList parameters = new List();
+ var parameters = new List();
int skip = function.IsBound ? 1 : 0;
foreach (IEdmOperationParameter edmParameter in function.Parameters.Skip(skip))
{
- if (parameterNameMapping != null)
+ if (parameterNameMapping != null && !parameterNameMapping.ContainsKey(edmParameter.Name))
{
- if (!parameterNameMapping.ContainsKey(edmParameter.Name))
- {
- continue;
- }
- }
+ continue;
+ }
OpenApiParameter parameter;
bool isOptionalParameter = edmParameter is IEdmOptionalParameter;
@@ -103,10 +101,10 @@ public static IList CreateParameters(this ODataContext context
{
Schema = new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
},
// These Parameter Objects optionally can contain the field description,
@@ -129,7 +127,7 @@ public static IList CreateParameters(this ODataContext context
Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name],
In = isOptionalParameter ? ParameterLocation.Query : ParameterLocation.Path,
Required = !isOptionalParameter,
- Schema = context.CreateEdmTypeSchema(edmParameter.Type)
+ Schema = context.CreateEdmTypeSchemaForParameter(edmParameter.Type)
};
}
@@ -184,10 +182,10 @@ public static IList CreateKeyParameters(this ODataContext cont
In = ParameterLocation.Path,
Required = true,
Description = $"The unique identifier of {entityType.Name}",
- Schema = context.CreateEdmTypeSchema(keys.First().Type)
+ Schema = context.CreateEdmTypeSchemaForParameter(keys[0].Type)
};
- parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name));
+ parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiAny(entityType.Name));
parameters.Add(parameter);
}
else
@@ -203,7 +201,7 @@ public static IList CreateKeyParameters(this ODataContext cont
In = ParameterLocation.Path,
Required = true,
Description = $"Property in multi-part unique identifier of {entityType.Name}",
- Schema = context.CreateEdmTypeSchema(keyProperty.Type)
+ Schema = context.CreateEdmTypeSchemaForParameter(keyProperty.Type)
};
if (keySegment.KeyMappings != null)
@@ -212,7 +210,7 @@ public static IList CreateKeyParameters(this ODataContext cont
parameter.Description += $", {keyProperty.Name}={quote}{{{parameter.Name}}}{quote}";
}
- parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name));
+ parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiAny(entityType.Name));
parameters.Add(parameter);
}
}
@@ -246,7 +244,7 @@ private static IList CreateAlternateKeyParameters(ODataContext
Name = alternateKey.First().Key,
In = ParameterLocation.Path,
Description = $"Alternate key of {entityType.Name}",
- Schema = context.CreateEdmTypeSchema(alternateKey.First().Value.Type),
+ Schema = context.CreateEdmTypeSchemaForParameter(alternateKey.First().Value.Type),
Required = true
}
);
@@ -264,7 +262,7 @@ private static IList CreateAlternateKeyParameters(ODataContext
Name = compositekey.Key,
In = ParameterLocation.Path,
Description = $"Property in multi-part alternate key of {entityType.Name}",
- Schema = context.CreateEdmTypeSchema(compositekey.Value.Type),
+ Schema = context.CreateEdmTypeSchemaForParameter(compositekey.Value.Type),
Required = true
}
);
@@ -281,9 +279,9 @@ private static IList CreateAlternateKeyParameters(ODataContext
/// The ODataPath
/// The OData context.
/// The created list of
- public static List CreatePathParameters(this ODataPath path, ODataContext context)
+ public static List CreatePathParameters(this ODataPath path, ODataContext context)
{
- List pathParameters = new();
+ List pathParameters = [];
var parameterMappings = path.CalculateParameterMapping(context.Settings);
foreach (ODataKeySegment keySegment in path.OfType())
@@ -301,7 +299,7 @@ public static List CreatePathParameters(this ODataPath path, O
if (operationSegment.ParameterMappings != null)
{
- IList parameters = context.CreateParameters(function, operationSegment.ParameterMappings);
+ var parameters = context.CreateParameters(function, operationSegment.ParameterMappings);
foreach (var parameter in parameters)
{
pathParameters.AppendParameter(parameter);
@@ -310,7 +308,7 @@ public static List CreatePathParameters(this ODataPath path, O
else
{
IDictionary mappings = parameterMappings[operationSegment];
- IList parameters = context.CreateParameters(function, mappings);
+ var parameters = context.CreateParameters(function, mappings);
pathParameters.AddRange(parameters);
}
}
@@ -331,7 +329,7 @@ public static List CreatePathParameters(this ODataPath path, O
///
/// The list of OpenApiParameters to be appended to
/// The new OpenApiParameter to be appended
- public static void AppendParameter(this IList parameters, OpenApiParameter parameter)
+ public static void AppendParameter(this IList parameters, IOpenApiParameter parameter)
{
HashSet parametersSet = new(parameters.Select(p => p.Name));
@@ -343,7 +341,10 @@ public static void AppendParameter(this IList parameters, Open
index++;
}
- parameter.Name = parameterName;
+ if (parameter is OpenApiParameter openApiParameter)
+ {
+ openApiParameter.Name = parameterName;
+ }
parametersSet.Add(parameterName);
parameters.Add(parameter);
}
@@ -354,7 +355,7 @@ public static void AppendParameter(this IList parameters, Open
/// The OData context.
/// The Edm annotation target.
/// The created or null.
- public static OpenApiParameter CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -362,11 +363,7 @@ public static OpenApiParameter CreateTop(this ODataContext context, IEdmVocabula
bool? top = context.Model.GetBoolean(target, CapabilitiesConstants.TopSupported);
if (top == null || top.Value)
{
- return new OpenApiParameter
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference { Type = ReferenceType.Parameter, Id = "top" }
- };
+ return new OpenApiParameterReference("top");
}
return null;
@@ -378,7 +375,7 @@ public static OpenApiParameter CreateTop(this ODataContext context, IEdmVocabula
/// The OData context.
/// The string representation of the Edm target path.
///
- public static OpenApiParameter CreateTop(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateTop(this ODataContext context, string targetPath)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -396,7 +393,7 @@ public static OpenApiParameter CreateTop(this ODataContext context, string targe
/// The OData context.
/// The Edm annotation target.
/// The created or null.
- public static OpenApiParameter CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -404,11 +401,7 @@ public static OpenApiParameter CreateSkip(this ODataContext context, IEdmVocabul
bool? skip = context.Model.GetBoolean(target, CapabilitiesConstants.SkipSupported);
if (skip == null || skip.Value)
{
- return new OpenApiParameter
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference { Type = ReferenceType.Parameter, Id = "skip" }
- };
+ return new OpenApiParameterReference("skip");
}
return null;
@@ -420,7 +413,7 @@ public static OpenApiParameter CreateSkip(this ODataContext context, IEdmVocabul
/// The OData context.
/// The string representation of the Edm target path.
///
- public static OpenApiParameter CreateSkip(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateSkip(this ODataContext context, string targetPath)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -438,7 +431,7 @@ public static OpenApiParameter CreateSkip(this ODataContext context, string targ
/// The OData context.
/// The Edm annotation target.
/// The created or null.
- public static OpenApiParameter CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -446,11 +439,7 @@ public static OpenApiParameter CreateSearch(this ODataContext context, IEdmVocab
SearchRestrictionsType search = context.Model.GetRecord(target, CapabilitiesConstants.SearchRestrictions);
if (search == null || search.IsSearchable)
{
- return new OpenApiParameter
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference { Type = ReferenceType.Parameter, Id = "search" }
- };
+ return new OpenApiParameterReference("search");
}
return null;
@@ -461,7 +450,7 @@ public static OpenApiParameter CreateSearch(this ODataContext context, IEdmVocab
/// The OData context.
/// The string representation of the Edm target path.
///
- public static OpenApiParameter CreateSearch(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateSearch(this ODataContext context, string targetPath)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -479,7 +468,7 @@ public static OpenApiParameter CreateSearch(this ODataContext context, string ta
/// The OData context.
/// The Edm annotation target.
/// The created or null.
- public static OpenApiParameter CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -487,11 +476,7 @@ public static OpenApiParameter CreateCount(this ODataContext context, IEdmVocabu
CountRestrictionsType count = context.Model.GetRecord(target, CapabilitiesConstants.CountRestrictions);
if (count == null || count.IsCountable)
{
- return new OpenApiParameter
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference { Type = ReferenceType.Parameter, Id = "count" }
- };
+ return new OpenApiParameterReference("count");
}
return null;
@@ -503,7 +488,7 @@ public static OpenApiParameter CreateCount(this ODataContext context, IEdmVocabu
/// The OData context.
/// The string representation of the Edm target path.
///
- public static OpenApiParameter CreateCount(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateCount(this ODataContext context, string targetPath)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -521,7 +506,7 @@ public static OpenApiParameter CreateCount(this ODataContext context, string tar
/// The OData context.
/// The Edm annotation target.
/// The created or null.
- public static OpenApiParameter CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
@@ -529,11 +514,7 @@ public static OpenApiParameter CreateFilter(this ODataContext context, IEdmVocab
FilterRestrictionsType filter = context.Model.GetRecord(target, CapabilitiesConstants.FilterRestrictions);
if (filter == null || filter.IsFilterable)
{
- return new OpenApiParameter
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference { Type = ReferenceType.Parameter, Id = "filter" }
- };
+ return new OpenApiParameterReference("filter");
}
return null;
@@ -545,7 +526,7 @@ public static OpenApiParameter CreateFilter(this ODataContext context, IEdmVocab
/// The OData context.
/// The string representation of the Edm target path.
///
- public static OpenApiParameter CreateFilter(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateFilter(this ODataContext context, string targetPath)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -626,7 +607,7 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVoca
return null;
}
- IList orderByItems = new List();
+ IList orderByItems = new List();
foreach (var property in structuredType.StructuralProperties())
{
if (sort != null && sort.IsNonSortableProperty(property.Name))
@@ -640,17 +621,17 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVoca
{
if (isAscOnly)
{
- orderByItems.Add(new OpenApiString(property.Name));
+ orderByItems.Add(property.Name);
}
else
{
- orderByItems.Add(new OpenApiString(property.Name + " desc"));
+ orderByItems.Add(property.Name + " desc");
}
}
else
{
- orderByItems.Add(new OpenApiString(property.Name));
- orderByItems.Add(new OpenApiString(property.Name + " desc"));
+ orderByItems.Add(property.Name);
+ orderByItems.Add(property.Name + " desc");
}
}
@@ -661,11 +642,11 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVoca
Description = "Order items by property values",
Schema = new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
UniqueItems = true,
Items = new OpenApiSchema
{
- Type = "string",
+ Type = JsonSchemaType.String,
Enum = context.Settings.UseStringArrayForQueryOptionsSchema ? null : orderByItems
}
},
@@ -743,11 +724,11 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocab
return null;
}
- IList selectItems = new List();
+ IList selectItems = new List();
foreach (var property in structuredType.StructuralProperties())
{
- selectItems.Add(new OpenApiString(property.Name));
+ selectItems.Add(property.Name);
}
foreach (var property in structuredType.NavigationProperties())
@@ -757,7 +738,7 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocab
continue;
}
- selectItems.Add(new OpenApiString(property.Name));
+ selectItems.Add(property.Name);
}
return new OpenApiParameter
@@ -767,11 +748,11 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocab
Description = "Select properties to be returned",
Schema = new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
UniqueItems = true,
Items = new OpenApiSchema
{
- Type = "string",
+ Type = JsonSchemaType.String,
Enum = context.Settings.UseStringArrayForQueryOptionsSchema ? null : selectItems
}
},
@@ -849,10 +830,7 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmVocab
return null;
}
- IList expandItems = new List
- {
- new OpenApiString("*")
- };
+ IList expandItems = [ "*" ];
foreach (var property in structuredType.NavigationProperties())
{
@@ -861,7 +839,7 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmVocab
continue;
}
- expandItems.Add(new OpenApiString(property.Name));
+ expandItems.Add(property.Name);
}
return new OpenApiParameter
@@ -871,11 +849,11 @@ public static OpenApiParameter CreateExpand(this ODataContext context, IEdmVocab
Description = "Expand related entities",
Schema = new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
UniqueItems = true,
Items = new OpenApiSchema
{
- Type = "string",
+ Type = JsonSchemaType.String,
Enum = context.Settings.UseStringArrayForQueryOptionsSchema ? null : expandItems
}
},
@@ -894,10 +872,11 @@ private static OpenApiParameter CreateTop(int topExample)
Description = "Show only the first n items",
Schema = new OpenApiSchema
{
- Type = "integer",
+ Type = JsonSchemaType.Number,
+ Format = "int64",
Minimum = 0,
},
- Example = new OpenApiInteger(topExample),
+ Example = topExample,
Style = ParameterStyle.Form,
Explode = false
};
@@ -913,7 +892,8 @@ private static OpenApiParameter CreateSkip()
Description = "Skip the first n items",
Schema = new OpenApiSchema
{
- Type = "integer",
+ Type = JsonSchemaType.Number,
+ Format = "int64",
Minimum = 0,
},
Style = ParameterStyle.Form,
@@ -931,7 +911,7 @@ private static OpenApiParameter CreateCount()
Description = "Include count of items",
Schema = new OpenApiSchema
{
- Type = "boolean"
+ Type = JsonSchemaType.Boolean
},
Style = ParameterStyle.Form,
Explode = false
@@ -948,7 +928,7 @@ private static OpenApiParameter CreateFilter()
Description = "Filter items by property values",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
},
Style = ParameterStyle.Form,
Explode = false
@@ -965,7 +945,7 @@ private static OpenApiParameter CreateSearch()
Description = "Search items by search phrases",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
},
Style = ParameterStyle.Form,
Explode = false
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
index 572c95f44..f74b51c27 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs
@@ -7,6 +7,7 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.PathItem;
@@ -22,22 +23,23 @@ internal static class OpenApiPathItemGenerator
/// Create a map of .
///
/// The OData context.
- /// The created map of .
- public static IDictionary CreatePathItems(this ODataContext context)
+ /// The Open API document to use to lookup references.
+ public static void AddPathItemsToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
- IDictionary pathItems = new Dictionary();
if (context.EntityContainer == null)
{
- return pathItems;
+ return;
}
+ document.Paths ??= [];
OpenApiConvertSettings settings = context.Settings.Clone();
settings.EnableKeyAsSegment = context.KeyAsSegment;
foreach (ODataPath path in context.AllPaths)
{
- IPathItemHandler handler = context.PathItemHanderProvider.GetHandler(path.Kind);
+ IPathItemHandler handler = context.PathItemHandlerProvider.GetHandler(path.Kind);
if (handler == null)
{
continue;
@@ -49,7 +51,7 @@ public static IDictionary CreatePathItems(this ODataCon
continue;
}
- pathItems.TryAddPath(context, path, pathItem);
+ document.Paths.TryAddPath(context, path, pathItem);
}
if (settings.ShowRootPath)
@@ -72,15 +74,13 @@ public static IDictionary CreatePathItems(this ODataCon
}
}
};
- pathItems.Add("/", rootPath);
+ document.Paths.Add("/", rootPath);
}
-
- return pathItems;
}
- private static IDictionary CreateRootLinks(IEdmEntityContainer entityContainer)
+ private static IDictionary CreateRootLinks(IEdmEntityContainer entityContainer)
{
- var links = new Dictionary();
+ var links = new Dictionary();
foreach (var element in entityContainer.Elements)
{
links.Add(element.Name, new OpenApiLink());
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathsGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathsGenerator.cs
index 49ebe109b..dfb0661d4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathsGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathsGenerator.cs
@@ -22,21 +22,16 @@ internal static class OpenApiPathsGenerator
/// and whose value is a Path Item Object.
///
/// The OData context.
- /// The created object.
- public static OpenApiPaths CreatePaths(this ODataContext context)
+ /// The Open API document to use to lookup references.
+ public static void AddPathsToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
// 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
// information desired in the Paths Object.
- OpenApiPaths paths = new();
- foreach (var item in context.CreatePathItems())
- {
- paths.Add(item.Key, item.Value);
- }
-
- return paths;
+ context.AddPathItemsToDocument(document);
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
index 04418da50..068ff77ab 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiRequestBodyGenerator.cs
@@ -9,6 +9,8 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Common;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -62,8 +64,8 @@ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IE
OpenApiSchema parametersSchema = new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary()
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary()
};
foreach (var parameter in action.Parameters.Skip(skip))
@@ -90,33 +92,22 @@ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IE
/// Create a dictionary of indexed by ref name.
///
/// The OData context.
- /// The created dictionary of indexed by ref name
- public static IDictionary CreateRequestBodies(this ODataContext context)
+ /// The OpenApi document to lookup references.
+ public static void AddRequestBodiesToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
- Dictionary requestBodies = new()
- {
- {
- Constants.ReferencePostRequestBodyName,
- CreateRefPostRequestBody()
- },
- {
- Constants.ReferencePutRequestBodyName,
- CreateRefPutRequestBody()
- }
- };
+ document.AddComponent(Constants.ReferencePostRequestBodyName, CreateRefPostRequestBody());
+ document.AddComponent(Constants.ReferencePutRequestBodyName, CreateRefPutRequestBody());
// add request bodies for actions targeting multiple related paths
foreach (IEdmAction action in context.Model.SchemaElements.OfType()
- .Where(action => context.Model.OperationTargetsMultiplePaths(action)))
+ .Where(context.Model.OperationTargetsMultiplePaths))
{
- OpenApiRequestBody requestBody = context.CreateRequestBody(action);
- if (requestBody != null)
- requestBodies.Add($"{action.Name}RequestBody", requestBody);
+ if (context.CreateRequestBody(action) is OpenApiRequestBody requestBody)
+ document.AddComponent($"{action.Name}RequestBody", requestBody);
}
-
- return requestBodies;
}
///
@@ -125,15 +116,7 @@ public static IDictionary CreateRequestBodies(this O
/// The created
private static OpenApiRequestBody CreateRefPostRequestBody()
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceCreateSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.ReferenceCreateSchemaName);
return new OpenApiRequestBody
{
Required = true,
@@ -156,15 +139,7 @@ private static OpenApiRequestBody CreateRefPostRequestBody()
/// The created
private static OpenApiRequestBody CreateRefPutRequestBody()
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceUpdateSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.ReferenceUpdateSchemaName);
return new OpenApiRequestBody
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
index 4c044bb59..6756ddaea 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
@@ -3,10 +3,13 @@
// 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.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
@@ -18,59 +21,22 @@ namespace Microsoft.OpenApi.OData.Generator
///
internal static class OpenApiResponseGenerator
{
- private static IDictionary _responses =
- new Dictionary
- {
- { Constants.StatusCodeDefault,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Response,
- Id = Constants.Error
- }
- }
- },
-
- { Constants.StatusCode204, new OpenApiResponse { Description = Constants.Success} },
- { Constants.StatusCode201, new OpenApiResponse { Description = Constants.Created} },
- { Constants.StatusCodeClass2XX, new OpenApiResponse { Description = Constants.Success} },
- { Constants.StatusCodeClass4XX, new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Response,
- Id = Constants.Error
- }
- }
- },
- { Constants.StatusCodeClass5XX, new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Response,
- Id = Constants.Error
- }
- }
- }
- };
-
///
- /// Get the for the build-in statusCode.
+ /// Get the for the build-in statusCode.
///
/// The status code.
- /// The created .
- public static OpenApiResponse GetResponse(this string statusCode)
+ /// The created .
+ public static IOpenApiResponse GetResponse(this string statusCode)
{
- if (_responses.TryGetValue(statusCode, out OpenApiResponse response))
- {
- return response;
- }
-
- return null;
+ return statusCode switch {
+ Constants.StatusCodeDefault => new OpenApiResponseReference(Constants.Error),
+ Constants.StatusCode204 => new OpenApiResponse { Description = Constants.Success},
+ Constants.StatusCode201 => new OpenApiResponse { Description = Constants.Created},
+ Constants.StatusCodeClass2XX => new OpenApiResponse { Description = Constants.Success},
+ Constants.StatusCodeClass4XX => new OpenApiResponseReference(Constants.Error),
+ Constants.StatusCodeClass5XX => new OpenApiResponseReference(Constants.Error),
+ _ => null,
+ };
}
///
@@ -80,10 +46,11 @@ public static OpenApiResponse GetResponse(this string statusCode)
/// that is referenced from all operations of the service.
///
/// The OData context.
- /// The name/value pairs for the standard OData error response.
- public static IDictionary CreateResponses(this ODataContext context)
+ /// The OpenApi document to lookup references.
+ public static void AddResponsesToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
var responses = new Dictionary
{
@@ -118,7 +85,10 @@ public static IDictionary CreateResponses(this ODataCon
responses[$"{operation.Name}Response"] = response;
}
- return responses;
+ foreach (var response in responses)
+ {
+ document.AddComponent(response.Key, response.Value);
+ }
}
///
@@ -156,15 +126,7 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
{
responses.Add(
context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference()
- {
- Type = ReferenceType.Response,
- Id = $"{operation.Name}Response"
- }
- }
+ new OpenApiResponseReference($"{operation.Name}Response")
);
}
else
@@ -191,13 +153,13 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
if (operation.ReturnType == null)
return null;
- OpenApiSchema schema;
+ IOpenApiSchema schema;
if (operation.ReturnType.IsCollection())
{
OpenApiSchema baseSchema = new()
{
- Type = Constants.ObjectType,
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{
"value", context.CreateEdmTypeSchema(operation.ReturnType)
@@ -210,20 +172,13 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
{
schema = new OpenApiSchema
{
- AllOf = new List
- {
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = operation.IsDeltaFunction() ? Constants.BaseDeltaFunctionResponse // @odata.nextLink + @odata.deltaLink
- : Constants.BaseCollectionPaginationCountResponse // @odata.nextLink + @odata.count
- }
- },
+ AllOf =
+ [
+ new OpenApiSchemaReference(operation.IsDeltaFunction() ? Constants.BaseDeltaFunctionResponse // @odata.nextLink + @odata.deltaLink
+ : Constants.BaseCollectionPaginationCountResponse // @odata.nextLink + @odata.count)
+ ),
baseSchema
- }
+ ]
};
}
else if (operation.IsDeltaFunction())
@@ -245,9 +200,12 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
schema = baseSchema;
}
- schema.Title = operation.ReturnType.Definition.AsElementType() is not IEdmEntityType entityType
- ? null : $"Collection of {entityType.Name}";
- schema.Type = "object";
+ if (schema is OpenApiSchema openApiSchema)
+ {
+ openApiSchema.Title = operation.ReturnType.Definition.AsElementType() is not IEdmEntityType entityType
+ ? null : $"Collection of {entityType.Name}";
+ openApiSchema.Type = JsonSchemaType.Object;
+ }
}
else if (operation.ReturnType.IsPrimitive())
{
@@ -255,8 +213,8 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
// whose name is value and whose value is a primitive value.
schema = new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{
"value", context.CreateEdmTypeSchema(operation.ReturnType)
@@ -315,15 +273,7 @@ private static OpenApiResponse CreateCollectionResponse(string typeName)
Constants.ApplicationJsonMediaType,
new OpenApiMediaType
{
- Schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{typeName}{Constants.CollectionSchemaSuffix}"
- }
- }
+ Schema = new OpenApiSchemaReference($"{typeName}{Constants.CollectionSchemaSuffix}")
}
}
}
@@ -332,14 +282,7 @@ private static OpenApiResponse CreateCollectionResponse(string typeName)
private static OpenApiResponse CreateCountResponse()
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new() {
- Type = ReferenceType.Schema,
- Id = Constants.DollarCountSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.DollarCountSchemaName);
return new OpenApiResponse
{
Description = "The count of the resource",
@@ -368,15 +311,7 @@ private static OpenApiResponse CreateErrorResponse(this ODataContext context)
Constants.ApplicationJsonMediaType,
new OpenApiMediaType
{
- Schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{errorNamespaceName}{OpenApiErrorSchemaGenerator.ODataErrorClassName}"
- }
- }
+ Schema = new OpenApiSchemaReference($"{errorNamespaceName}{OpenApiErrorSchemaGenerator.ODataErrorClassName}")
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
index 2834322ed..eaf3609cc 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
@@ -7,7 +7,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.OData.Edm;
-using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.OData.Properties;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
@@ -17,6 +16,12 @@
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.MicrosoftExtensions;
using Microsoft.OpenApi.OData.Vocabulary.Core;
+using System.Text.Json.Nodes;
+using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models.References;
+using System.Globalization;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -26,142 +31,141 @@ namespace Microsoft.OpenApi.OData.Generator
internal static class OpenApiSchemaGenerator
{
///
- /// Create the dictionary of object.
- /// The name of each pair is the namespace-qualified name of the type. It uses the namespace instead of the alias.
- /// The value of each pair is a .
+ /// Adds the component schemas to the Open API document.
///
/// The OData to Open API context.
- /// The string/schema dictionary.
- public static IDictionary CreateSchemas(this ODataContext context)
+ /// The Open API document to use for references lookup.
+ public static void AddSchemasToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
-
- IDictionary schemas = new Dictionary();
-
- // 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.
- // Ideally this would be driven off the types used in the paths, but in practice, it is simply
- // all of the types present in the model.
- IEnumerable elements = context.Model.GetAllElements();
-
- foreach (var element in elements)
- {
- switch (element.SchemaElementKind)
- {
- case EdmSchemaElementKind.TypeDefinition: // Type definition
- {
- IEdmType reference = (IEdmType)element;
- var fullTypeName = reference.FullTypeName();
- if(reference is IEdmComplexType &&
- fullTypeName.Split(new char[] {'.'}, StringSplitOptions.RemoveEmptyEntries)
- .Last()
- .Equals(context.Settings.InnerErrorComplexTypeName, StringComparison.Ordinal))
- continue;
-
- schemas.Add(fullTypeName, context.CreateSchemaTypeSchema(reference));
- }
- break;
- }
- }
+ Utils.CheckArgumentNull(document, nameof(document));
// append the Edm.Spatial
foreach(var schema in context.CreateSpatialSchemas())
{
- schemas[schema.Key] = schema.Value;
+ document.AddComponent(schema.Key, schema.Value);
}
// append the OData errors
foreach(var schema in context.CreateODataErrorSchemas())
{
- schemas[schema.Key] = schema.Value;
+ document.AddComponent(schema.Key, schema.Value);
}
if(context.Settings.EnableDollarCountPath)
- schemas[Constants.DollarCountSchemaName] = new OpenApiSchema {
- Type = "integer",
- Format = "int32"
- };
+ document.AddComponent(Constants.DollarCountSchemaName, new OpenApiSchema {
+ Type = JsonSchemaType.Number,
+ Format = "int64"
+ });
- schemas = schemas.Concat(context.GetAllCollectionEntityTypes()
- .Select(x => new KeyValuePair(
- $"{(x is IEdmEntityType eType ? eType.FullName() : x.FullTypeName())}{Constants.CollectionSchemaSuffix}",
- CreateCollectionSchema(context, x)))
- .Where(x => !schemas.ContainsKey(x.Key)))
- .Concat(context.GetAllCollectionComplexTypes()
- .Select(x => new KeyValuePair(
- $"{x.FullTypeName()}{Constants.CollectionSchemaSuffix}",
- CreateCollectionSchema(context, x)))
- .Where(x => !schemas.ContainsKey(x.Key)))
- .ToDictionary(x => x.Key, x => x.Value);
-
if(context.HasAnyNonContainedCollections())
{
- schemas[$"String{Constants.CollectionSchemaSuffix}"] = CreateCollectionSchema(context, new OpenApiSchema { Type = Constants.StringType }, Constants.StringType);
+ document.AddComponent($"String{Constants.CollectionSchemaSuffix}", CreateCollectionSchema(context, new OpenApiSchema { Type = JsonSchemaType.String }, Constants.StringType));
}
- schemas[Constants.ReferenceUpdateSchemaName] = new()
+ document.AddComponent(Constants.ReferenceUpdateSchemaName, new OpenApiSchema()
{
- Type = Constants.ObjectType,
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
- {Constants.OdataId, new OpenApiSchema { Type = Constants.StringType, Nullable = false }},
- {Constants.OdataType, new OpenApiSchema { Type = Constants.StringType, Nullable = true }},
+ {Constants.OdataId, new OpenApiSchema { Type = JsonSchemaType.String }},
+ {Constants.OdataType, new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null }},
}
- };
+ });
- schemas[Constants.ReferenceCreateSchemaName] = new()
+ document.AddComponent(Constants.ReferenceCreateSchemaName, new OpenApiSchema()
{
- Type = Constants.ObjectType,
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
- {Constants.OdataId, new OpenApiSchema { Type = Constants.StringType, Nullable = false }}
+ {Constants.OdataId, new OpenApiSchema { Type = JsonSchemaType.String }}
},
- AdditionalProperties = new OpenApiSchema { Type = Constants.ObjectType }
- };
+ AdditionalProperties = new OpenApiSchema { Type = JsonSchemaType.Object }
+ });
- schemas[Constants.ReferenceNumericName] = new()
+ document.AddComponent(Constants.ReferenceNumericName, new OpenApiSchema()
{
- Type = Constants.StringType,
- Nullable = true,
+ Type = JsonSchemaType.String | JsonSchemaType.Null,
Enum =
[
- new OpenApiString("-INF"),
- new OpenApiString("INF"),
- new OpenApiString("NaN")
+ "-INF",
+ "INF",
+ "NaN"
]
- };
+ });
if (context.Settings.EnableODataAnnotationReferencesForResponses)
{
// @odata.nextLink + @odata.count
if (context.Settings.EnablePagination || context.Settings.EnableCount)
{
- schemas[Constants.BaseCollectionPaginationCountResponse] = new()
+ var responseSchema = new OpenApiSchema()
{
Title = "Base collection pagination and count responses",
- Type = Constants.ObjectType,
+ Type = JsonSchemaType.Object,
};
+ document.AddComponent(Constants.BaseCollectionPaginationCountResponse, responseSchema);
if (context.Settings.EnableCount)
- schemas[Constants.BaseCollectionPaginationCountResponse].Properties.Add(ODataConstants.OdataCount);
+ responseSchema.Properties.Add(ODataConstants.OdataCount);
if (context.Settings.EnablePagination)
- schemas[Constants.BaseCollectionPaginationCountResponse].Properties.Add(ODataConstants.OdataNextLink);
+ responseSchema.Properties.Add(ODataConstants.OdataNextLink);
}
// @odata.nextLink + @odata.deltaLink
if (context.Model.SchemaElements.OfType().Any(static x => x.IsDeltaFunction()))
{
- schemas[Constants.BaseDeltaFunctionResponse] = new()
+ document.AddComponent(Constants.BaseDeltaFunctionResponse, new OpenApiSchema()
{
Title = "Base delta function response",
- Type = Constants.ObjectType
- };
- schemas[Constants.BaseDeltaFunctionResponse].Properties.Add(ODataConstants.OdataNextLink);
- schemas[Constants.BaseDeltaFunctionResponse].Properties.Add(ODataConstants.OdataDeltaLink);
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
+ {
+ {ODataConstants.OdataNextLink.Key, ODataConstants.OdataNextLink.Value},
+ {ODataConstants.OdataDeltaLink.Key, ODataConstants.OdataDeltaLink.Value}
+ }
+ });
+ }
+ }
+
+ // 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.
+ // Ideally this would be driven off the types used in the paths, but in practice, it is simply
+ // all of the types present in the model.
+ IEnumerable elements = context.Model.GetAllElements();
+
+ foreach (var element in elements)
+ {
+ switch (element.SchemaElementKind)
+ {
+ case EdmSchemaElementKind.TypeDefinition: // Type definition
+ {
+ IEdmType reference = (IEdmType)element;
+ var fullTypeName = reference.FullTypeName();
+ if(reference is IEdmComplexType &&
+ fullTypeName.Split(['.'], StringSplitOptions.RemoveEmptyEntries)
+ .Last()
+ .Equals(context.Settings.InnerErrorComplexTypeName, StringComparison.Ordinal))
+ continue;
+
+ document.AddComponent(fullTypeName, context.CreateSchemaTypeSchema(reference));
+ }
+ break;
}
}
- return schemas;
+ foreach(var collectionEntry in context.GetAllCollectionEntityTypes()
+ .Select(x => new KeyValuePair(
+ $"{(x is IEdmEntityType eType ? eType.FullName() : x.FullTypeName())}{Constants.CollectionSchemaSuffix}",
+ CreateCollectionSchema(context, x)))
+ .Concat(context.GetAllCollectionComplexTypes()
+ .Select(x => new KeyValuePair(
+ $"{x.FullTypeName()}{Constants.CollectionSchemaSuffix}",
+ CreateCollectionSchema(context, x))))
+ .ToArray())
+ {
+ document.AddComponent(collectionEntry.Key, collectionEntry.Value);
+ }
}
internal static bool HasAnyNonContainedCollections(this ODataContext context)
{
@@ -206,7 +210,7 @@ internal static IEnumerable GetAllCollectionEntityTypes(this
private static OpenApiSchema CreateCollectionSchema(ODataContext context, IEdmStructuredType structuredType)
{
- OpenApiSchema schema = null;
+ IOpenApiSchema schema = null;
var entityType = structuredType as IEdmEntityType;
if (context.Settings.EnableDerivedTypesReferencesForResponses && entityType != null)
@@ -216,27 +220,19 @@ private static OpenApiSchema CreateCollectionSchema(ODataContext context, IEdmSt
if (schema == null)
{
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = entityType?.FullName() ?? structuredType.FullTypeName()
- }
- };
+ schema = new OpenApiSchemaReference(entityType?.FullName() ?? structuredType.FullTypeName());
}
return CreateCollectionSchema(context, schema, entityType?.Name ?? structuredType.FullTypeName());
}
- private static OpenApiSchema CreateCollectionSchema(ODataContext context, OpenApiSchema schema, string typeName)
+ private static OpenApiSchema CreateCollectionSchema(ODataContext context, IOpenApiSchema schema, string typeName)
{
- var properties = new Dictionary
+ var properties = new Dictionary
{
{
"value",
new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = schema
}
}
@@ -244,7 +240,7 @@ private static OpenApiSchema CreateCollectionSchema(ODataContext context, OpenAp
OpenApiSchema baseSchema = new()
{
- Type = Constants.ObjectType,
+ Type = JsonSchemaType.Object,
Properties = properties
};
@@ -254,23 +250,15 @@ private static OpenApiSchema CreateCollectionSchema(ODataContext context, OpenAp
if (context.Settings.EnableODataAnnotationReferencesForResponses)
{
// @odata.nextLink + @odata.count
- OpenApiSchema paginationCountSchema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.BaseCollectionPaginationCountResponse
- }
- };
+ var paginationCountSchema = new OpenApiSchemaReference(Constants.BaseCollectionPaginationCountResponse);
collectionSchema = new OpenApiSchema
{
- AllOf = new List
- {
+ AllOf =
+ [
paginationCountSchema,
baseSchema
- }
+ ]
};
}
else
@@ -290,7 +278,7 @@ private static OpenApiSchema CreateCollectionSchema(ODataContext context, OpenAp
}
collectionSchema.Title = $"Collection of {typeName}";
- collectionSchema.Type = Constants.ObjectType;
+ collectionSchema.Type = JsonSchemaType.Object;
return collectionSchema;
}
@@ -310,10 +298,10 @@ public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdm
OpenApiSchema schema = new()
{
// An enumeration type is represented as a Schema Object of type string
- Type = Constants.StringType,
+ Type = JsonSchemaType.String,
// containing the OpenAPI Specification enum keyword.
- Enum = new List(),
+ Enum = new List(),
// It optionally can contain the field description,
// whose value is the value of the unqualified annotation Core.Description of the enumeration type.
@@ -331,7 +319,8 @@ public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdm
}
var extension = (context.Settings.OpenApiSpecVersion == OpenApiSpecVersion.OpenApi2_0 ||
- context.Settings.OpenApiSpecVersion == OpenApiSpecVersion.OpenApi3_0 ) &&
+ context.Settings.OpenApiSpecVersion == OpenApiSpecVersion.OpenApi3_0 ||
+ context.Settings.OpenApiSpecVersion == OpenApiSpecVersion.OpenApi3_1) &&
context.Settings.AddEnumDescriptionExtension ?
new OpenApiEnumValuesDescriptionExtension {
EnumName = enumType.Name,
@@ -341,7 +330,7 @@ public static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEdm
// Enum value is an array that contains a string with the member name for each enumeration member.
foreach (IEdmEnumMember member in enumType.Members)
{
- schema.Enum.Add(new OpenApiString(member.Name));
+ schema.Enum.Add(member.Name);
AddEnumDescription(member, extension, context);
}
@@ -387,28 +376,30 @@ public static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context
///
/// The OData context.
/// The Edm property.
- /// The created .
- public static OpenApiSchema CreatePropertySchema(this ODataContext context, IEdmProperty property)
+ /// The created .
+ public static IOpenApiSchema CreatePropertySchema(this ODataContext context, IEdmProperty property)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(property, nameof(property));
- OpenApiSchema schema = context.CreateEdmTypeSchema(property.Type);
+ var schema = context.CreateEdmTypeSchema(property.Type);
- switch (property.PropertyKind)
+
+ if (schema is OpenApiSchema openApiSchema)
{
- case EdmPropertyKind.Structural:
- IEdmStructuralProperty structuralProperty = (IEdmStructuralProperty)property;
- schema.Default = CreateDefault(structuralProperty);
- break;
- }
+ if (property.PropertyKind is EdmPropertyKind.Structural &&
+ property is IEdmStructuralProperty structuralProperty)
+ {
+ openApiSchema.Default = CreateDefault(structuralProperty);
+ }
- // The Schema Object for a property optionally can contain the field description,
- // whose value is the value of the unqualified annotation Core.Description of the property.
- schema.Description = context.Model.GetDescriptionAnnotation(property);
+ // The Schema Object for a property optionally can contain the field description,
+ // whose value is the value of the unqualified annotation Core.Description of the property.
+ openApiSchema.Description = context.Model.GetDescriptionAnnotation(property);
- // Set property with Computed Annotation in CSDL to readonly
- schema.ReadOnly = context.Model.GetBoolean(property, CoreConstants.Computed) ?? false;
+ // Set property with Computed Annotation in CSDL to readonly
+ openApiSchema.ReadOnly = context.Model.GetBoolean(property, CoreConstants.Computed) ?? false;
+ }
return schema;
}
@@ -419,42 +410,52 @@ public static OpenApiSchema CreatePropertySchema(this ODataContext context, IEdm
/// The OData context.
/// The Edm structured type.
/// The created map of .
- public static IDictionary CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType)
+ public static IDictionary 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 properties = new Dictionary();
+ var properties = new Dictionary();
// structure properties
foreach (var property in structuredType.DeclaredStructuralProperties())
{
- OpenApiSchema propertySchema = context.CreatePropertySchema(property);
- propertySchema.Description = context.Model.GetDescriptionAnnotation(property);
- propertySchema.Extensions.AddCustomAttributesToExtensions(context, property);
+ var propertySchema = context.CreatePropertySchema(property);
+ if (propertySchema is OpenApiSchema openApiSchema)
+ {
+ openApiSchema.Description = context.Model.GetDescriptionAnnotation(property);
+ // we always want a new copy because it's a reference
+ openApiSchema.Extensions = propertySchema.Extensions is null ? [] : new Dictionary(propertySchema.Extensions);
+ openApiSchema.Extensions.AddCustomAttributesToExtensions(context, property);
+ }
properties.Add(property.Name, propertySchema);
}
// navigation properties
foreach (var property in structuredType.DeclaredNavigationProperties())
{
- OpenApiSchema propertySchema = context.CreateEdmTypeSchema(property.Type);
- propertySchema.Description = context.Model.GetDescriptionAnnotation(property);
- propertySchema.Extensions.AddCustomAttributesToExtensions(context, property);
- propertySchema.Extensions.Add(Constants.xMsNavigationProperty, new OpenApiBoolean(true));
+ var propertySchema = context.CreateEdmTypeSchema(property.Type);
+ if (propertySchema is OpenApiSchema openApiSchema)
+ {
+ openApiSchema.Description = context.Model.GetDescriptionAnnotation(property);
+ // we always want a new copy because it's a reference
+ openApiSchema.Extensions = propertySchema.Extensions is null ? [] : new Dictionary(propertySchema.Extensions);
+ openApiSchema.Extensions.AddCustomAttributesToExtensions(context, property);
+ openApiSchema.Extensions.Add(Constants.xMsNavigationProperty, new OpenApiAny(true));
+ }
properties.Add(property.Name, propertySchema);
}
return properties;
}
- public static OpenApiSchema CreateSchemaTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinition typeDefinition)
+ public static IOpenApiSchema CreateSchemaTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinition typeDefinition)
{
return context.CreateSchema(typeDefinition.UnderlyingType);
}
- internal static OpenApiSchema CreateSchemaTypeSchema(this ODataContext context, IEdmType edmType)
+ internal static IOpenApiSchema CreateSchemaTypeSchema(this ODataContext context, IEdmType edmType)
{
Debug.Assert(context != null);
Debug.Assert(edmType != null);
@@ -473,7 +474,7 @@ internal static OpenApiSchema CreateSchemaTypeSchema(this ODataContext context,
case EdmTypeKind.None:
default:
- throw Error.NotSupported(String.Format(SRResource.NotSupportedEdmTypeKind, edmType.TypeKind));
+ throw Error.NotSupported(string.Format(SRResource.NotSupportedEdmTypeKind, edmType.TypeKind));
}
}
@@ -483,7 +484,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
Debug.Assert(context != null);
Debug.Assert(structuredType != null);
- IOpenApiAny example = null;
+ JsonNode example = null;
if (context.Settings.ShowSchemaExamples)
{
example = CreateStructuredTypePropertiesExample(context, structuredType);
@@ -502,7 +503,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
{
extension = new Dictionary
{
- { Constants.xMsDiscriminatorValue, new OpenApiString("#" + structuredType.FullTypeName()) }
+ { Constants.xMsDiscriminatorValue, new OpenApiAny("#" + structuredType.FullTypeName()) }
};
}
@@ -512,22 +513,14 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
{
Extensions = extension,
- AllOf = new List
- {
+ AllOf =
+ [
// 1. a JSON Reference to the Schema Object of the base type
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = structuredType.BaseType.FullTypeName()
- }
- },
+ new OpenApiSchemaReference(structuredType.BaseType.FullTypeName()),
// 2. a Schema Object describing the derived type
context.CreateStructuredTypeSchema(structuredType, false, false, derivedTypes)
- },
+ ],
AnyOf = null,
OneOf = null,
@@ -542,14 +535,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
if (context.Settings.EnableDiscriminatorValue && derivedTypes.Any())
{
Dictionary mapping = derivedTypes
- .ToDictionary(x => $"#{x.FullTypeName()}", x => new OpenApiSchema
- {
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = x.FullTypeName()
- }
- }.Reference.ReferenceV3);
+ .ToDictionary(x => $"#{x.FullTypeName()}", x => new OpenApiSchemaReference(x.FullTypeName()).Reference.ReferenceV3);
discriminator = new OpenApiDiscriminator
{
@@ -563,7 +549,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
{
Title = (structuredType as IEdmSchemaElement)?.Name,
- Type = Constants.ObjectType,
+ Type = JsonSchemaType.Object,
Discriminator = discriminator,
@@ -579,7 +565,7 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
if (context.Settings.EnableDiscriminatorValue)
{
- OpenApiString defaultValue = null;
+ JsonNode defaultValue = null;
bool isBaseTypeEntity = Constants.EntityName.Equals(structuredType.BaseType?.FullTypeName().Split('.').Last(), StringComparison.OrdinalIgnoreCase);
bool isBaseTypeAbstractNonEntity = (structuredType.BaseType?.IsAbstract ?? false) && !isBaseTypeEntity;
@@ -587,12 +573,12 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
isBaseTypeAbstractNonEntity ||
context.Model.IsBaseTypeReferencedAsTypeInModel(structuredType.BaseType))
{
- defaultValue = new("#" + structuredType.FullTypeName());
+ defaultValue = "#" + structuredType.FullTypeName();
}
if (!schema.Properties.TryAdd(Constants.OdataType, new OpenApiSchema()
{
- Type = Constants.StringType,
+ Type = JsonSchemaType.String,
Default = defaultValue,
}))
{
@@ -624,34 +610,24 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
}
}
- private static IOpenApiAny CreateStructuredTypePropertiesExample(ODataContext context, IEdmStructuredType structuredType)
+ internal static JsonObject CreateStructuredTypePropertiesExample(ODataContext context, IEdmStructuredType structuredType)
{
- OpenApiObject example = new OpenApiObject();
-
- IEdmEntityType entityType = structuredType as IEdmEntityType;
+ JsonObject example = [];
// properties
foreach (var property in structuredType.Properties())
{
- // IOpenApiAny item;
IEdmTypeReference propertyType = property.Type;
- IOpenApiAny item = GetTypeNameForExample(context, propertyType);
+ JsonNode item = GetTypeNameForExample(context, propertyType);
- EdmTypeKind typeKind = propertyType.TypeKind();
- if (typeKind == EdmTypeKind.Primitive && item is OpenApiString)
+ if (propertyType.TypeKind() == EdmTypeKind.Primitive &&
+ item is JsonValue jsonValue &&
+ jsonValue.TryGetValue(out string stringAny) &&
+ structuredType is IEdmEntityType entityType &&
+ entityType.Key().Any(k => StringComparer.Ordinal.Equals(k.Name, property.Name)))
{
- 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);
+ item = $"{stringAny} (identifier)";
}
example.Add(property.Name, item);
@@ -660,58 +636,64 @@ private static IOpenApiAny CreateStructuredTypePropertiesExample(ODataContext co
return example;
}
- private static IOpenApiAny GetTypeNameForExample(ODataContext context, IEdmTypeReference edmTypeReference)
+ private static JsonNode GetTypeNameForPrimitive(ODataContext context, IEdmTypeReference edmTypeReference)
{
- switch (edmTypeReference.TypeKind())
- {
- case EdmTypeKind.Primitive:
- IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition();
- OpenApiSchema schema = context.CreateSchema(primitiveType);
+ IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition();
+ IOpenApiSchema schema = context.CreateSchema(primitiveType);
- if (edmTypeReference.IsBoolean())
- {
- return new OpenApiBoolean(true);
- }
- else
- {
- if (schema.Reference != null)
- {
- return new OpenApiString(schema.Reference.Id);
- }
- else
- {
- return new OpenApiString(schema.Type ??
- (schema.AnyOf ?? Enumerable.Empty())
- .Union(schema.AllOf ?? Enumerable.Empty())
- .Union(schema.OneOf ?? Enumerable.Empty())
- .FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? schema.Format);
- }
- }
-
- case EdmTypeKind.Entity:
- case EdmTypeKind.Complex:
- case EdmTypeKind.Enum:
- OpenApiObject obj = new OpenApiObject();
- obj[Constants.OdataType] = new OpenApiString(edmTypeReference.FullName());
- return obj;
-
- case EdmTypeKind.Collection:
- OpenApiArray array = new OpenApiArray();
- IEdmTypeReference elementType = edmTypeReference.AsCollection().ElementType();
- array.Add(GetTypeNameForExample(context, elementType));
- return array;
+ if (edmTypeReference.IsBoolean())
+ {
+ return true;
+ }
+ else
+ {
+ if (schema is OpenApiSchemaReference { Reference.Id: not null } reference && !string.IsNullOrEmpty(reference.Reference.Id))
+ {
+ return reference.Reference.Id;
+ }
+ else
+ {
+ return schema.Type.ToIdentifier() ??
+ (schema.AnyOf ?? Enumerable.Empty())
+ .Union(schema.AllOf ?? Enumerable.Empty())
+ .Union(schema.OneOf ?? Enumerable.Empty())
+ .FirstOrDefault(static x => !string.IsNullOrEmpty(x.Format))?.Format ?? schema.Format;
+ }
+ }
+ }
- case EdmTypeKind.Untyped:
- return new OpenApiObject();
+ private static JsonNode GetTypeNameForExample(ODataContext context, IEdmTypeReference edmTypeReference)
+ {
+ return edmTypeReference.TypeKind() switch
+ {
+ // return new OpenApiBinary(new byte[] { 0x00 }); issue on binary writing
+ EdmTypeKind.Primitive when edmTypeReference.IsBinary() => Convert.ToBase64String(new byte[] { 0x00 }),
+ EdmTypeKind.Primitive when edmTypeReference.IsBoolean() => true,
+ EdmTypeKind.Primitive when edmTypeReference.IsByte() => 0x00,
+ EdmTypeKind.Primitive when edmTypeReference.IsDate() => DateTime.MinValue.ToString("o", CultureInfo.InvariantCulture),
+ EdmTypeKind.Primitive when edmTypeReference.IsDateTimeOffset() => DateTimeOffset.MinValue.ToString("o", CultureInfo.InvariantCulture),
+ EdmTypeKind.Primitive when edmTypeReference.IsGuid() => Guid.Empty.ToString("D", CultureInfo.InvariantCulture),
+ EdmTypeKind.Primitive when edmTypeReference.IsInt16() ||
+ edmTypeReference.IsInt32() ||
+ edmTypeReference.IsDecimal() ||
+ edmTypeReference.IsInt64() ||
+ edmTypeReference.IsFloating() ||
+ edmTypeReference.IsDouble() => 0,
+ EdmTypeKind.Primitive => GetTypeNameForPrimitive(context, edmTypeReference),
+
+ EdmTypeKind.Entity or EdmTypeKind.Complex or EdmTypeKind.Enum => new JsonObject()
+ {//TODO this is wrong for enums, and should instead use one of the enum members
+ [Constants.OdataType] = edmTypeReference.FullName()
+ },
- case EdmTypeKind.TypeDefinition:
- case EdmTypeKind.EntityReference:
- default:
- throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind());
- }
+ EdmTypeKind.Collection => new JsonArray(GetTypeNameForExample(context, edmTypeReference.AsCollection().ElementType())),
+ EdmTypeKind.TypeDefinition => GetTypeNameForExample(context, new EdmPrimitiveTypeReference(edmTypeReference.AsTypeDefinition().TypeDefinition().UnderlyingType, edmTypeReference.IsNullable)),
+ EdmTypeKind.Untyped => new JsonObject(),
+ _ => throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind()),
+ };
}
- private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
+ private static JsonNode CreateDefault(this IEdmStructuralProperty property)
{
if (property == null ||
property.DefaultValueString == null)
@@ -721,7 +703,7 @@ private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
if (property.Type.IsEnum())
{
- return new OpenApiString(property.DefaultValueString);
+ return property.DefaultValueString;
}
if (!property.Type.IsPrimitive())
@@ -734,10 +716,9 @@ private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
{
case EdmPrimitiveTypeKind.Boolean:
{
- bool result;
- if (Boolean.TryParse(property.DefaultValueString, out result))
+ if (bool.TryParse(property.DefaultValueString, out bool result))
{
- return new OpenApiBoolean(result);
+ return result;
}
}
break;
@@ -745,10 +726,9 @@ private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
case EdmPrimitiveTypeKind.Int16:
case EdmPrimitiveTypeKind.Int32:
{
- int result;
- if (Int32.TryParse(property.DefaultValueString, out result))
+ if (int.TryParse(property.DefaultValueString, out int result))
{
- return new OpenApiInteger(result);
+ return result;
}
}
break;
@@ -769,7 +749,7 @@ private static IOpenApiAny CreateDefault(this IEdmStructuralProperty property)
break;
}
- return new OpenApiString(property.DefaultValueString);
+ return property.DefaultValueString;
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
index 8df137aea..93b32e330 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs
@@ -10,6 +10,7 @@
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Authorization;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
+using Microsoft.OpenApi.Models.References;
namespace Microsoft.OpenApi.OData.Generator
{
@@ -18,39 +19,6 @@ namespace Microsoft.OpenApi.OData.Generator
///
internal static class OpenApiSecurityRequirementGenerator
{
- ///
- /// Create the list of object.
- ///
- /// The OData to Open API context.
- /// The securitySchemes.
- /// The created collection.
- public static IEnumerable CreateSecurityRequirements(this ODataContext context,
- IList securitySchemes)
- {
- Utils.CheckArgumentNull(context, nameof(context));
-
- if (securitySchemes != null)
- {
- foreach (var securityScheme in securitySchemes)
- {
- yield return new OpenApiSecurityRequirement
- {
- [
- new OpenApiSecurityScheme
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.SecurityScheme,
- Id = securityScheme.Authorization
- }
- }
- ] = new List(securityScheme.RequiredScopes ?? new List())
- };
- }
- }
- }
-
///
/// Create the list of object.
///
@@ -69,15 +37,7 @@ public static IEnumerable CreateSecurityRequirements
yield return new OpenApiSecurityRequirement
{
[
- new OpenApiSecurityScheme
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.SecurityScheme,
- Id = permission.SchemeName
- }
- }
+ new OpenApiSecuritySchemeReference(permission.SchemeName)
] = new List(permission.Scopes?.Select(c => c.Scope) ?? new List())
};
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
index f0cfb92cc..e5156a837 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs
@@ -24,21 +24,15 @@ internal static class OpenApiSecuritySchemeGenerator
/// The name of each pair is the name of authorization. The value of each pair is a .
///
/// The OData to Open API context.
- /// The string/security scheme dictionary.
- public static IDictionary CreateSecuritySchemes(this ODataContext context)
+ /// The Open API document.
+ public static void AddSecuritySchemesToDocument(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
- if (context.Model == null || context.Model.EntityContainer == null)
+ if (context.Model == null || context.Model.EntityContainer == null || context.Model.GetAuthorizations(context.EntityContainer) is not {} authorizations)
{
- return null;
- }
-
- IDictionary securitySchemes = new Dictionary();
- var authorizations = context.Model.GetAuthorizations(context.EntityContainer);
- if (authorizations == null)
- {
- return securitySchemes;
+ return;
}
foreach (var authorization in authorizations)
@@ -68,10 +62,8 @@ public static IDictionary CreateSecuritySchemes(t
break;
}
- securitySchemes[authorization.Name] = scheme;
+ document.AddComponent(authorization.Name, scheme);
}
-
- return securitySchemes;
}
private static void AppendApiKey(OpenApiSecurityScheme scheme, ApiKey apiKey)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSpatialTypeSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSpatialTypeSchemaGenerator.cs
index 3fcd31680..3bbdb43b2 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSpatialTypeSchemaGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSpatialTypeSchemaGenerator.cs
@@ -4,8 +4,10 @@
// ------------------------------------------------------------
using System.Collections.Generic;
-using Microsoft.OpenApi.Any;
+using System.Text.Json.Nodes;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
@@ -23,11 +25,11 @@ internal static class OpenApiSpatialTypeSchemaGenerator
///
/// The OData to Open API context.
/// The string/schema dictionary.
- public static IDictionary CreateSpatialSchemas(this ODataContext context)
+ public static IDictionary CreateSpatialSchemas(this ODataContext context)
{
Utils.CheckArgumentNull(context, nameof(context));
- IDictionary schemas = new Dictionary();
+ var schemas = new Dictionary();
if (context.IsSpatialTypeUsed)
{
@@ -73,136 +75,72 @@ public static IDictionary CreateSpatialSchemas(this OData
/// Create for Edm.Geography.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographySchema()
+ public static IOpenApiSchema CreateEdmGeographySchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.Geometry"
- }
- };
+ return new OpenApiSchemaReference("Edm.Geometry");
}
///
/// Create for Edm.GeographyPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyPointSchema()
+ public static IOpenApiSchema CreateEdmGeographyPointSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPoint"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryPoint");
}
///
/// Create for Edm.GeographyLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyLineStringSchema()
+ public static IOpenApiSchema CreateEdmGeographyLineStringSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryLineString"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryLineString");
}
///
/// Create for Edm.GeographyPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyPolygonSchema()
+ public static IOpenApiSchema CreateEdmGeographyPolygonSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPolygon"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryPolygon");
}
///
/// Create for Edm.GeographyMultiPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiPointSchema()
+ public static IOpenApiSchema CreateEdmGeographyMultiPointSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPoint"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiPoint");
}
///
/// Create for Edm.GeographyMultiLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiLineStringSchema()
+ public static IOpenApiSchema CreateEdmGeographyMultiLineStringSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiLineString"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiLineString");
}
///
/// Create for Edm.GeographyMultiPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiPolygonSchema()
+ public static IOpenApiSchema CreateEdmGeographyMultiPolygonSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPolygon"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiPolygon");
}
///
/// Create for Edm.GeographyCollection.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyCollectionSchema()
+ public static IOpenApiSchema CreateEdmGeographyCollectionSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryCollection"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryCollection");
}
///
@@ -213,17 +151,17 @@ public static OpenApiSchema CreateEdmGeometrySchema()
{
return new OpenApiSchema
{
- Type = "object",
- OneOf = new List
- {
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryPoint" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryLineString" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryPolygon" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryMultiPoint" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryMultiLineString" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryMultiPolygon" } },
- new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.GeometryCollection" } }
- }
+ Type = JsonSchemaType.Object,
+ OneOf =
+ [
+ new OpenApiSchemaReference("Edm.GeometryPoint"),
+ new OpenApiSchemaReference("Edm.GeometryLineString"),
+ new OpenApiSchemaReference("Edm.GeometryPolygon"),
+ new OpenApiSchemaReference("Edm.GeometryMultiPoint"),
+ new OpenApiSchemaReference("Edm.GeometryMultiLineString"),
+ new OpenApiSchemaReference("Edm.GeometryMultiPolygon"),
+ new OpenApiSchemaReference("Edm.GeometryCollection"),
+ ]
};
}
@@ -235,20 +173,20 @@ public static OpenApiSchema CreateEdmGeometryPointSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Type = "string",
- Enum = new List
+ Type = JsonSchemaType.String,
+ Enum = new List
{
- new OpenApiString("Point")
+ "Point"
},
- Default = new OpenApiString("Point")
+ Default = "Point"
}
},
- { "coordinates", new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" } } }
+ { "coordinates", new OpenApiSchemaReference("GeoJSON.position") }
},
Required = new HashSet
{
@@ -266,21 +204,21 @@ public static OpenApiSchema CreateEdmGeometryLineStringSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("LineString")
+ "LineString"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" }},
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("GeoJSON.position"),
MinItems = 2
}
}
@@ -301,24 +239,24 @@ public static OpenApiSchema CreateEdmGeometryPolygonSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("Polygon")
+ "Polygon"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" } }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("GeoJSON.position")
},
MinItems = 4
}
@@ -340,21 +278,21 @@ public static OpenApiSchema CreateEdmGeometryMultiPointSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("MultiPoint")
+ "MultiPoint"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" }}
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("GeoJSON.position")
}
}
},
@@ -374,24 +312,24 @@ public static OpenApiSchema CreateEdmGeometryMultiLineStringSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("MultiLineString")
+ "MultiLineString"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" } }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("GeoJSON.position")
},
MinItems = 2
}
@@ -413,27 +351,27 @@ public static OpenApiSchema CreateEdmGeometryMultiPolygonSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("MultiPolygon")
+ "MultiPolygon"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "GeoJSON.position" } }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("GeoJSON.position")
}
},
MinItems = 4
@@ -456,21 +394,21 @@ public static OpenApiSchema CreateEdmGeometryCollectionSchema()
{
return new OpenApiSchema
{
- Type = "object",
- Properties = new Dictionary
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
{
{ "type", new OpenApiSchema
{
- Enum = new List
+ Enum = new List
{
- new OpenApiString("GeometryCollection")
+ "GeometryCollection"
},
}
},
{ "coordinates", new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { UnresolvedReference = true, Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Edm.Geometry" } }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference("Edm.Geometry")
}
}
},
@@ -490,8 +428,8 @@ public static OpenApiSchema CreateGeoJsonPointSchema()
{
return new OpenApiSchema
{
- Type = "array",
- Items = new OpenApiSchema { Type = "number" },
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchema { Type = JsonSchemaType.Number },
MinItems = 2
};
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
index 0b4aa2a10..3a8e8260e 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
+++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
@@ -54,7 +54,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs
index 2344f3880..4515aec96 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs
@@ -4,7 +4,7 @@
// ------------------------------------------------------------
using Microsoft.OpenApi.Models;
-using Microsoft.OpenApi.OData.Common;
+using Microsoft.OpenApi.Models.Interfaces;
using System.Collections.Generic;
namespace Microsoft.OpenApi.OData
@@ -24,16 +24,16 @@ internal static class ODataConstants
///
/// @odata.nextLink KeyValue pair
///
- public static KeyValuePair OdataNextLink = new("@odata.nextLink", new OpenApiSchema { Type = Constants.StringType, Nullable = true });
+ public static KeyValuePair OdataNextLink = new("@odata.nextLink", new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null });
///
/// @odata.count KeyValue pair
///
- public static KeyValuePair OdataCount = new("@odata.count", new OpenApiSchema { Type = "integer", Format = "int64", Nullable = true });
+ public static KeyValuePair OdataCount = new("@odata.count", new OpenApiSchema { Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "int64"});
///
/// @odata.deltaLink KeyValue pair
///
- public static KeyValuePair OdataDeltaLink = new("@odata.deltaLink", new OpenApiSchema { Type = Constants.StringType, Nullable = true });
+ public static KeyValuePair OdataDeltaLink = new("@odata.deltaLink", new OpenApiSchema { Type = JsonSchemaType.String | JsonSchemaType.Null });
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
index 188675bf7..ecb73a7d4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs
@@ -66,7 +66,7 @@ public class OpenApiConvertSettings
/// Gets/sets a value indicating whether the version of openApi to serialize to is v2.
/// Currently only impacts nullable references for EdmTypeSchemaGenerator
///
- public OpenApiSpecVersion OpenApiSpecVersion { get; set; } = OpenApiSpecVersion.OpenApi3_0;
+ public OpenApiSpecVersion OpenApiSpecVersion { get; set; } = OpenApiSpecVersion.OpenApi3_1;
///
/// Gets/sets a value indicating to set the OperationId on Open API operation.
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/CachedOperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/CachedOperationHandlerProvider.cs
new file mode 100644
index 000000000..5fac7c1b6
--- /dev/null
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/CachedOperationHandlerProvider.cs
@@ -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 System.Collections.Generic;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.OData.Common;
+using Microsoft.OpenApi.OData.Edm;
+
+namespace Microsoft.OpenApi.OData.Operation;
+
+///
+/// A class to provide the .
+///
+internal class CachedOperationHandlerProvider : IOperationHandlerProvider
+{
+ private readonly IOperationHandlerProvider _concreteProvider;
+ private readonly Dictionary<(ODataPathKind, OperationType), IOperationHandler> _cache = new();
+ public CachedOperationHandlerProvider(IOperationHandlerProvider concreteProvider)
+ {
+ Utils.CheckArgumentNull(concreteProvider, nameof(concreteProvider));
+ _concreteProvider = concreteProvider;
+ }
+ ///
+ public IOperationHandler GetHandler(ODataPathKind pathKind, OperationType operationType)
+ {
+ if (!_cache.TryGetValue((pathKind, operationType), out IOperationHandler handler))
+ {
+ handler = _concreteProvider.GetHandler(pathKind, operationType);
+ _cache[(pathKind, operationType)] = handler;
+ }
+ return handler;
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
index 426386b2b..33bd1ffc5 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
@@ -5,6 +5,7 @@
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
@@ -29,15 +30,11 @@ protected override void SetTags(OpenApiOperation operation)
if (!string.IsNullOrEmpty(tagName))
{
- OpenApiTag tag = new()
- {
- Name = tagName
- };
-
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
- operation.Tags.Add(tag);
-
- Context.AppendTag(tag);
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
+ operation.Tags.Add(new OpenApiTagReference(tagName));
}
base.SetTags(operation);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
index 1f8d3124f..4bc44f072 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyGetOperationHandler.cs
@@ -3,11 +3,13 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
-using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -54,7 +56,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- OpenApiParameter parameter;
+ IOpenApiParameter parameter;
if(ComplexPropertySegment.Property.Type.IsCollection())
{
// The parameters array contains Parameter Objects for all system query options allowed for this collection,
@@ -130,12 +132,12 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (Context.Settings.EnablePagination && ComplexPropertySegment.Property.Type.IsCollection())
{
- OpenApiObject extension = new()
+ JsonObject extension = new()
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
base.SetExtensions(operation);
}
@@ -149,15 +151,7 @@ protected override void SetResponses(OpenApiOperation operation)
}
else
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = ComplexPropertySegment.ComplexType.FullName()
- }
- };
+ var schema = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName());
SetSingleResponse(operation, schema);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
index 6fd736c64..736931c1d 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
@@ -8,6 +8,7 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -65,7 +66,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
@@ -128,16 +129,8 @@ private OpenApiSchema GetOpenApiSchema()
{
return new()
{
- Type = "array",
- Items = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = ComplexPropertySegment.ComplexType.FullName()
- }
- }
+ Type = JsonSchemaType.Array,
+ Items = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName())
};
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
index cb9e616f1..f101f2118 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
@@ -7,6 +7,8 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -16,16 +18,15 @@ namespace Microsoft.OpenApi.OData.Operation;
internal abstract class ComplexPropertyUpdateOperationHandler : ComplexPropertyBaseOperationHandler
{
-
private UpdateRestrictionsType _updateRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- var complexPropertyUpdateRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions);
- _updateRestrictions?.MergePropertiesIfNull(complexPropertyUpdateRestrictions);
+ _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ var complexPropertyUpdateRestrictions = Context.Model.GetRecord(ComplexPropertySegment.Property, CapabilitiesConstants.UpdateRestrictions);
+ _updateRestrictions?.MergePropertiesIfNull(complexPropertyUpdateRestrictions);
_updateRestrictions ??= complexPropertyUpdateRestrictions;
}
@@ -39,7 +40,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
// OperationId
if (Context.Settings.EnableOperationId)
- {
+ {
string prefix = OperationType == OperationType.Patch ? "Update" : "Set";
operation.OperationId = EdmModelHelper.GenerateComplexPropertyPathOperationId(Path, Context, prefix);
}
@@ -100,39 +101,31 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private OpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema GetOpenApiSchema()
{
- var schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = ComplexPropertySegment.ComplexType.FullName()
- }
- };
-
- if (ComplexPropertySegment.Property.Type.IsCollection())
- {
+ var schema = new OpenApiSchemaReference(ComplexPropertySegment.ComplexType.FullName());
+
+ if (ComplexPropertySegment.Property.Type.IsCollection())
+ {
return new OpenApiSchema
{
- Type = Constants.ObjectType,
- Properties = new Dictionary
- {
- {
+ Type = JsonSchemaType.Object,
+ Properties = new Dictionary
+ {
+ {
"value",
new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = schema
- }
- }
+ }
+ }
}
- };
- }
- else
- {
- return schema;
+ };
+ }
+ else
+ {
+ return schema;
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
index 69b76302b..7fd5fa0c9 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/DollarCountGetOperationHandler.cs
@@ -3,11 +3,15 @@
// 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.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -31,7 +35,7 @@ internal class DollarCountGetOperationHandler : OperationHandler
private ODataSegment firstSegment;
private int pathCount;
private const int SecondLastSegmentIndex = 2;
- private IEdmVocabularyAnnotatable annotatable;
+ private readonly List annotatables = [];
///
protected override void Initialize(ODataContext context, ODataPath path)
@@ -39,20 +43,32 @@ protected override void Initialize(ODataContext context, ODataPath path)
base.Initialize(context, path);
// Get the first segment
- firstSegment = path.Segments.First();
+ firstSegment = path.Segments[0];
// get the last second segment
pathCount = path.Segments.Count;
if(pathCount >= SecondLastSegmentIndex)
- SecondLastSegment = path.Segments.ElementAt(pathCount - SecondLastSegmentIndex);
+ SecondLastSegment = path.Segments[pathCount - SecondLastSegmentIndex];
- if (SecondLastSegment is ODataNavigationSourceSegment sourceSegment)
+ AddODataSegmentToAnnotables(SecondLastSegment, path.Segments.Count > SecondLastSegmentIndex ? path.Segments.SkipLast(SecondLastSegmentIndex).ToArray() : []);
+ }
+ private void AddODataSegmentToAnnotables(ODataSegment oDataSegment, ODataSegment[] oDataSegments)
+ {
+ if (oDataSegment is ODataNavigationSourceSegment sourceSegment)
+ {
+ annotatables.Add(sourceSegment.NavigationSource as IEdmEntitySet);
+ }
+ else if (oDataSegment is ODataNavigationPropertySegment navigationPropertySegment)
{
- annotatable = sourceSegment.NavigationSource as IEdmEntitySet;
+ annotatables.Add(navigationPropertySegment.NavigationProperty);
}
- else if (SecondLastSegment is ODataNavigationPropertySegment navigationPropertySegment)
+ else if (oDataSegment is ODataTypeCastSegment odataTypeCastSegment)
{
- annotatable = navigationPropertySegment.NavigationProperty;
+ annotatables.Add(odataTypeCastSegment.StructuredType as IEdmVocabularyAnnotatable);
+ if (annotatables.Count == 1 && oDataSegments.Length > 0)
+ {// we want to look at the parent navigation property or entity set
+ AddODataSegmentToAnnotables(oDataSegments[oDataSegments.Length - 1], oDataSegments.SkipLast(1).ToArray());
+ }
}
}
@@ -70,7 +86,7 @@ protected override void SetTags(OpenApiOperation operation)
}
else if (SecondLastSegment is ODataTypeCastSegment)
{
- ODataSegment lastThirdSegment = Path.Segments.ElementAt(pathCount - 3);
+ ODataSegment lastThirdSegment = Path.Segments[pathCount - 3];
if (lastThirdSegment is ODataNavigationSourceSegment sourceSegment2)
{
tagName = TagNameFromNavigationSourceSegment(sourceSegment2);
@@ -87,17 +103,12 @@ protected override void SetTags(OpenApiOperation operation)
if (tagName != null)
{
- OpenApiTag tag = new()
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
{
Name = tagName
- };
-
- // Use an extension for TOC (Table of Content)
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
-
- operation.Tags.Add(tag);
+ });
- Context.AppendTag(tag);
+ operation.Tags.Add(new OpenApiTagReference(tagName));
}
string TagNameFromNavigationSourceSegment(ODataNavigationSourceSegment sourceSegment)
@@ -152,14 +163,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
{
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference() {
- Type = ReferenceType.Response,
- Id = Constants.DollarCountSchemaName
- }
- }
+ new OpenApiResponseReference(Constants.DollarCountSchemaName)
}
};
operation.AddErrorResponses(Context.Settings, false);
@@ -172,20 +176,15 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- if (annotatable == null)
- {
- return;
- }
-
- OpenApiParameter parameter;
+ IOpenApiParameter parameter;
- parameter = Context.CreateSearch(TargetPath) ?? Context.CreateSearch(annotatable);
+ parameter = Context.CreateSearch(TargetPath) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateSearch(x)).FirstOrDefault(static x => x is not null));
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateFilter(TargetPath) ?? Context.CreateFilter(annotatable);
+ parameter = Context.CreateFilter(TargetPath) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateFilter(x)).FirstOrDefault(static x => x is not null));
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -194,15 +193,13 @@ protected override void SetParameters(OpenApiOperation operation)
protected override void AppendCustomParameters(OpenApiOperation operation)
{
- if (annotatable == null)
+ ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (annotatables.Count > 0)
{
- return;
+ ReadRestrictionsType annotatableReadRestrictions = annotatables.Select(x => Context.Model.GetRecord(x, CapabilitiesConstants.ReadRestrictions)).FirstOrDefault(static x => x is not null);
+ readRestrictions?.MergePropertiesIfNull(annotatableReadRestrictions);
+ readRestrictions ??= annotatableReadRestrictions;
}
-
- ReadRestrictionsType readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- ReadRestrictionsType annotatableReadRestrictions = Context.Model.GetRecord(annotatable, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(annotatableReadRestrictions);
- readRestrictions ??= annotatableReadRestrictions;
if (readRestrictions == null)
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
index f2f0424a9..2f27652d7 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
@@ -33,7 +33,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("actionImport"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("actionImport"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
index e099e3714..bb595c083 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionOperationHandler.cs
@@ -6,6 +6,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -45,15 +46,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
{
if (Context.Model.OperationTargetsMultiplePaths(action))
{
- operation.RequestBody = new OpenApiRequestBody
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.RequestBody,
- Id = $"{action.Name}RequestBody"
- }
- };
+ operation.RequestBody = new OpenApiRequestBodyReference($"{action.Name}RequestBody");
}
else
{
@@ -67,7 +60,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("action"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("action"));
base.SetExtensions(operation);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
index 9e36f21f4..b284e9791 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
@@ -24,7 +24,10 @@ protected override void SetParameters(OpenApiOperation operation)
{
base.SetParameters(operation);
- IEdmFunctionImport functionImport = EdmOperationImport as IEdmFunctionImport;
+ if (EdmOperationImport is not IEdmFunctionImport functionImport)
+ {
+ return;
+ }
if (OperationImportSegment.ParameterMappings != null)
{
@@ -47,7 +50,7 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("functionImport"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("functionImport"));
base.SetExtensions(operation);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
index 60184c8fe..995e3abaf 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
@@ -45,7 +45,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("function"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("function"));
base.SetExtensions(operation);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
index 91cee642a..30b745a81 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs
@@ -9,6 +9,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -129,35 +130,27 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
///
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]);
+ var tag = CreateTag(EdmOperationImport);
+ tag.Extensions.Add(Constants.xMsTocType, new OpenApiAny("container"));
+ Context.AppendTag(tag);
+ operation.Tags.Add(new OpenApiTagReference(tag.Name));
base.SetTags(operation);
}
- private static IList CreateTags(IEdmOperationImport operationImport)
+ private static OpenApiTag CreateTag(IEdmOperationImport operationImport)
{
- if (operationImport.EntitySet != null)
+ if (operationImport.EntitySet is IEdmPathExpression pathExpression)
{
- var pathExpression = operationImport.EntitySet as IEdmPathExpression;
- if (pathExpression != null)
+ return new OpenApiTag
{
- return new List
- {
- new OpenApiTag
- {
- Name = PathAsString(pathExpression.PathSegments)
- }
- };
- }
+ Name = PathAsString(pathExpression.PathSegments)
+ };
}
- return new List{
- new OpenApiTag
- {
- Name = operationImport.Name
- }
+ return new OpenApiTag
+ {
+ Name = operationImport.Name
};
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
index 404e936fa..33419aa0b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs
@@ -5,9 +5,11 @@
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -143,8 +145,8 @@ protected override void SetTags(OpenApiOperation operation)
{
Name = tagName,
};
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("container"));
- operation.Tags.Add(tag);
+ tag.Extensions.Add(Constants.xMsTocType, new OpenApiAny("container"));
+ operation.Tags.Add(new OpenApiTagReference(tag.Name));
Context.AppendTag(tag);
@@ -239,31 +241,31 @@ private void AppendSystemQueryOptions(IEdmFunction function, OpenApiOperation op
if (function.ReturnType.IsCollection())
{
// $top
- if (Context.CreateTop(function) is OpenApiParameter topParameter)
+ if (Context.CreateTop(function) is {} topParameter)
{
operation.Parameters.AppendParameter(topParameter);
}
// $skip
- if (Context.CreateSkip(function) is OpenApiParameter skipParameter)
+ if (Context.CreateSkip(function) is {} skipParameter)
{
operation.Parameters.AppendParameter(skipParameter);
}
// $search
- if (Context.CreateSearch(function) is OpenApiParameter searchParameter)
+ if (Context.CreateSearch(function) is {} searchParameter)
{
operation.Parameters.AppendParameter(searchParameter);
}
// $filter
- if (Context.CreateFilter(function) is OpenApiParameter filterParameter)
+ if (Context.CreateFilter(function) is {} filterParameter)
{
operation.Parameters.AppendParameter(filterParameter);
}
// $count
- if (Context.CreateCount(function) is OpenApiParameter countParameter)
+ if (Context.CreateCount(function) is {} countParameter)
{
operation.Parameters.AppendParameter(countParameter);
}
@@ -271,19 +273,19 @@ private void AppendSystemQueryOptions(IEdmFunction function, OpenApiOperation op
if (function.ReturnType?.Definition?.AsElementType() is IEdmEntityType entityType)
{
// $select
- if (Context.CreateSelect(function, entityType) is OpenApiParameter selectParameter)
+ if (Context.CreateSelect(function, entityType) is {} selectParameter)
{
operation.Parameters.AppendParameter(selectParameter);
}
// $orderby
- if (Context.CreateOrderBy(function, entityType) is OpenApiParameter orderbyParameter)
+ if (Context.CreateOrderBy(function, entityType) is {} orderbyParameter)
{
operation.Parameters.AppendParameter(orderbyParameter);
}
// $expand
- if (Context.CreateExpand(function, entityType) is OpenApiParameter expandParameter)
+ if (Context.CreateExpand(function, entityType) is {} expandParameter)
{
operation.Parameters.AppendParameter(expandParameter);
}
@@ -326,13 +328,13 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (Context.Settings.EnablePagination && EdmOperation.ReturnType?.TypeKind() == EdmTypeKind.Collection)
{
- OpenApiObject extension = new OpenApiObject
+ JsonObject extension = new JsonObject
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
index f34d83450..83933ba56 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
@@ -76,7 +76,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
index 8a506cf82..be37820c8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
@@ -11,6 +11,8 @@
using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.Models.References;
+using Microsoft.OpenApi.Models.Interfaces;
namespace Microsoft.OpenApi.OData.Operation
{
@@ -88,8 +90,8 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- OpenApiSchema schema = null;
- IDictionary links = null;
+ IOpenApiSchema schema = null;
+ IDictionary links = null;
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
@@ -104,15 +106,7 @@ protected override void SetResponses(OpenApiOperation operation)
if (schema == null)
{
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = EntitySet.EntityType.FullName()
- }
- };
+ schema = new OpenApiSchemaReference(EntitySet.EntityType.FullName());
}
operation.Responses = new OpenApiResponses
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
index 96b967d38..3c6af965c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
@@ -4,9 +4,11 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -57,12 +59,12 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (Context.Settings.EnablePagination)
{
- OpenApiObject extension = new OpenApiObject
+ JsonObject extension = new JsonObject
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
base.SetExtensions(operation);
}
@@ -78,7 +80,7 @@ protected override void SetParameters(OpenApiOperation operation)
// Capabilities.TopSupported, Capabilities.SkipSupported, Capabilities.SearchRestrictions,
// Capabilities.FilterRestrictions, and Capabilities.CountRestrictions
// $top
- OpenApiParameter parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(EntitySet);
+ var parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(EntitySet);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -145,15 +147,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
{
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference()
- {
- Type = ReferenceType.Response,
- Id = $"{EntitySet.EntityType.FullName()}{Constants.CollectionSchemaSuffix}"
- },
- }
+ new OpenApiResponseReference($"{EntitySet.EntityType.FullName()}{Constants.CollectionSchemaSuffix}")
}
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
index 58c3f66d9..2a71c84fe 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
@@ -6,6 +6,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
@@ -36,16 +37,14 @@ protected override void Initialize(ODataContext context, ODataPath path)
///
protected override void SetTags(OpenApiOperation operation)
{
- OpenApiTag tag = new OpenApiTag
- {
- Name = EntitySet.Name + "." + EntitySet.EntityType.Name,
- };
-
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
+ var tagName = EntitySet.Name + "." + EntitySet.EntityType.Name;
- operation.Tags.Add(tag);
+ operation.Tags.Add(new OpenApiTagReference(tagName));
- Context.AppendTag(tag);
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
base.SetTags(operation);
}
@@ -53,7 +52,7 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("operation"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
index 4367beacf..16987c879 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs
@@ -7,6 +7,8 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -122,7 +124,7 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
/// The entity content description.
private IDictionary GetContentDescription()
{
- OpenApiSchema schema = GetEntitySchema();
+ var schema = GetEntitySchema();
var content = new Dictionary();
if (EntitySet.EntityType.HasStream)
@@ -144,7 +146,7 @@ private IDictionary GetContentDescription()
{
Schema = new OpenApiSchema
{
- Type = "string",
+ Type = JsonSchemaType.String,
Format = "binary"
}
});
@@ -181,29 +183,11 @@ private IDictionary GetContentDescription()
/// Get the entity schema.
///
/// The entity schema.
- private OpenApiSchema GetEntitySchema()
+ private IOpenApiSchema GetEntitySchema()
{
- OpenApiSchema schema = null;
-
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
- {
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model);
- }
-
- if (schema == null)
- {
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = EntitySet.EntityType.FullName()
- }
- };
- }
-
- return schema;
+ return Context.Settings.EnableDerivedTypesReferencesForRequestBody ?
+ EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model) :
+ new OpenApiSchemaReference(EntitySet.EntityType.FullName());
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
index 3595b30b7..26e6aaa74 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
@@ -7,6 +7,8 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -76,7 +78,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
protected IDictionary GetContent()
{
- OpenApiSchema schema = GetOpenApiSchema();
+ var schema = GetOpenApiSchema();
var content = new Dictionary();
IEnumerable mediaTypes = _updateRestrictions?.RequestContentTypes;
@@ -138,22 +140,14 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private OpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema GetOpenApiSchema()
{
if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
return EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model);
}
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = EntitySet.EntityType.FullName()
- }
- };
+ return new OpenApiSchemaReference(EntitySet.EntityType.FullName());
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
index 54e712a2c..bcd947aa8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
@@ -73,7 +73,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
index 125141e98..20c10d1d3 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
@@ -23,27 +23,27 @@ internal class MediaEntityGetOperationHandler : MediaEntityOperationalHandler
public override OperationType OperationType => OperationType.Get;
private ReadRestrictionsType _readRestrictions = null;
- protected override void Initialize(ODataContext context, ODataPath path)
- {
- base.Initialize(context, path);
-
- if (Property != null)
- {
- _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- if (Property is IEdmNavigationProperty)
- {
- var navigationReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
- .RestrictedProperties?.FirstOrDefault()?.ReadRestrictions;
- _readRestrictions?.MergePropertiesIfNull(navigationReadRestrictions);
- _readRestrictions ??= navigationReadRestrictions;
- }
- else
- {
- var propertyReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.ReadRestrictions);
- _readRestrictions?.MergePropertiesIfNull(propertyReadRestrictions);
- _readRestrictions ??= propertyReadRestrictions;
- }
- }
+ protected override void Initialize(ODataContext context, ODataPath path)
+ {
+ base.Initialize(context, path);
+
+ if (Property != null)
+ {
+ _readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ if (Property is IEdmNavigationProperty)
+ {
+ var navigationReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
+ .RestrictedProperties?.FirstOrDefault()?.ReadRestrictions;
+ _readRestrictions?.MergePropertiesIfNull(navigationReadRestrictions);
+ _readRestrictions ??= navigationReadRestrictions;
+ }
+ else
+ {
+ var propertyReadRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.ReadRestrictions);
+ _readRestrictions?.MergePropertiesIfNull(propertyReadRestrictions);
+ _readRestrictions ??= propertyReadRestrictions;
+ }
+ }
}
///
@@ -51,7 +51,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
{
// Summary
string placeholderValue = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "media content";
- operation.Summary = _readRestrictions?.Description;
+ operation.Summary = _readRestrictions?.Description;
operation.Summary ??= IsNavigationPropertyPath
? $"Get {placeholderValue} for the navigation property {NavigationProperty.Name} from {NavigationSourceSegment.NavigationSource.Name}"
: $"Get {placeholderValue} for {NavigationSourceSegment.EntityType.Name} from {NavigationSourceSegment.Identifier}";
@@ -67,8 +67,8 @@ protected override void SetBasicInfo(OpenApiOperation operation)
?? Context.Model.GetDescriptionAnnotation(Property);
}
else
- {
- // Structural property
+ {
+ // Structural property
description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Property);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
index 3a159ace6..c7ac1fa47 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
@@ -6,6 +6,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
@@ -56,7 +57,7 @@ protected override void Initialize(ODataContext context, ODataPath path)
// Check whether path is a navigation property path
IsNavigationPropertyPath = Path.Segments.Contains(
- Path.Segments.Where(segment => segment is ODataNavigationPropertySegment).FirstOrDefault());
+ Path.Segments.FirstOrDefault(segment => segment is ODataNavigationPropertySegment));
LastSegmentIsStreamPropertySegment = Path.LastSegment.Kind == ODataSegmentKind.StreamProperty;
@@ -82,17 +83,12 @@ protected override void SetTags(OpenApiOperation operation)
? EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context)
: NavigationSourceSegment.Identifier + "." + NavigationSourceSegment.EntityType.Name;
- OpenApiTag tag = new()
- {
- Name = tagIdentifier
- };
-
- // Use an extension for TOC (Table of Content)
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
-
- operation.Tags.Add(tag);
- Context.AppendTag(tag);
+ Context.AddExtensionToTag(tagIdentifier, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagIdentifier
+ });
+ operation.Tags.Add(new OpenApiTagReference(tagIdentifier));
}
///
@@ -112,7 +108,7 @@ protected string GetOperationId(string prefix, string identifier)
Utils.CheckArgumentNullOrEmpty(prefix, nameof(prefix));
Utils.CheckArgumentNullOrEmpty(identifier, nameof(identifier));
- IList items = new List
+ var items = new List
{
NavigationSourceSegment.Identifier
};
@@ -146,7 +142,7 @@ protected string GetOperationId(string prefix, string identifier)
}
}
- return string.Join(".", items);
+ return $"{string.Join(".", items)}-{Path.GetPathHash(Context.Settings)}";
}
///
@@ -166,7 +162,7 @@ protected IDictionary GetContentDescription()
OpenApiSchema schema = new()
{
- Type = "string",
+ Type = JsonSchemaType.String,
Format = "binary"
};
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
index 20f810b84..e7f99e5ee 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs
@@ -8,6 +8,7 @@
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -29,23 +30,23 @@ protected override void Initialize(ODataContext context, ODataPath path)
{
base.Initialize(context, path);
- if (Property != null)
- {
- _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- if (Property is IEdmNavigationProperty)
- {
- var navigationUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
- .RestrictedProperties?.FirstOrDefault()?.UpdateRestrictions;
- _updateRestrictions?.MergePropertiesIfNull(navigationUpdateRestrictions);
- _updateRestrictions ??= navigationUpdateRestrictions;
- }
- else
- {
- var propertyUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.UpdateRestrictions);
- _updateRestrictions?.MergePropertiesIfNull(propertyUpdateRestrictions);
- _updateRestrictions ??= propertyUpdateRestrictions;
- }
- }
+ if (Property != null)
+ {
+ _updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ if (Property is IEdmNavigationProperty)
+ {
+ var navigationUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.NavigationRestrictions)?
+ .RestrictedProperties?.FirstOrDefault()?.UpdateRestrictions;
+ _updateRestrictions?.MergePropertiesIfNull(navigationUpdateRestrictions);
+ _updateRestrictions ??= navigationUpdateRestrictions;
+ }
+ else
+ {
+ var propertyUpdateRestrictions = Context.Model.GetRecord(Property, CapabilitiesConstants.UpdateRestrictions);
+ _updateRestrictions?.MergePropertiesIfNull(propertyUpdateRestrictions);
+ _updateRestrictions ??= propertyUpdateRestrictions;
+ }
+ }
}
///
@@ -90,15 +91,7 @@ protected override void SetResponses(OpenApiOperation operation)
// Get the entity type declaring this stream property.
(var entityType, _) = GetStreamElements();
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = entityType.FullName()
- }
- };
+ var schema = new OpenApiSchemaReference(entityType.FullName());
operation.AddErrorResponses(Context.Settings, addNoContent: true, schema: schema);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
index f12e9fa98..22d600a30 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
@@ -6,7 +6,6 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
-using Microsoft.OpenApi.OData.Generator;
namespace Microsoft.OpenApi.OData.Operation
{
@@ -46,7 +45,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
OpenApiSchema schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
};
operation.Responses = new OpenApiResponses
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
index 11e852053..ad0ac7eaa 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
@@ -61,7 +61,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
index fd94a4f50..40801332b 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
@@ -5,9 +5,12 @@
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -64,13 +67,13 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
- OpenApiObject extension = new OpenApiObject
+ JsonObject extension = new JsonObject
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
}
@@ -80,7 +83,7 @@ protected override void SetExtensions(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- IDictionary links = null;
+ IDictionary links = null;
if (Context.Settings.ShowLinks)
{
string operationId = GetOperationId();
@@ -96,22 +99,13 @@ protected override void SetResponses(OpenApiOperation operation)
{
{
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference()
- {
- Type = ReferenceType.Response,
- Id = $"{NavigationProperty.ToEntityType().FullName()}{Constants.CollectionSchemaSuffix}"
- },
- Links = links
- }
+ new OpenApiResponseReference($"{NavigationProperty.ToEntityType().FullName()}{Constants.CollectionSchemaSuffix}")
}
};
}
else
{
- OpenApiSchema schema = null;
+ IOpenApiSchema schema = null;
var entityType = NavigationProperty.ToEntityType();
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
@@ -119,18 +113,7 @@ protected override void SetResponses(OpenApiOperation operation)
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, Context.Model);
}
- if (schema == null)
- {
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = entityType.FullName()
- }
- };
- }
+ schema ??= new OpenApiSchemaReference(entityType.FullName());
operation.Responses = new OpenApiResponses
{
@@ -175,7 +158,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
// Need to verify that TopSupported or others should be applied to navigation source.
// So, how about for the navigation property.
- OpenApiParameter parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(NavigationProperty);
+ var parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(NavigationProperty);
if (parameter != null)
{
operation.Parameters.Add(parameter);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
index 743a10e88..a09511cba 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
@@ -6,6 +6,8 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary;
@@ -39,10 +41,10 @@ internal abstract class NavigationPropertyOperationHandler : OperationHandler
///
/// Gets a bool value indicating whether the last segment is a key segment.
///
- protected bool LastSegmentIsKeySegment { get; private set; }
-
- ///
- /// Gets a bool value indicating whether the second last segment in a $ref path is a key segment
+ protected bool LastSegmentIsKeySegment { get; private set; }
+
+ ///
+ /// Gets a bool value indicating whether the second last segment in a $ref path is a key segment
///
protected bool SecondLastSegmentIsKeySegment { get; private set; }
@@ -60,7 +62,7 @@ protected override void Initialize(ODataContext context, ODataPath path)
NavigationSource = navigationSourceSegment.NavigationSource;
LastSegmentIsKeySegment = path.LastSegment is ODataKeySegment;
- LastSegmentIsRefSegment = path.LastSegment is ODataRefSegment;
+ LastSegmentIsRefSegment = path.LastSegment is ODataRefSegment;
SecondLastSegmentIsKeySegment = Path.Segments.Reverse().Skip(1).Take(1).Single().Kind == ODataSegmentKind.Key;
NavigationProperty = path.OfType().Last().NavigationProperty;
@@ -85,14 +87,11 @@ protected override void Initialize(ODataContext context, ODataPath path)
protected override void SetTags(OpenApiOperation operation)
{
string name = EdmModelHelper.GenerateNavigationPropertyPathTagName(Path, Context);
- OpenApiTag tag = new()
- {
- Name = name
- };
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
- operation.Tags.Add(tag);
-
- Context.AppendTag(tag);
+ Context.AddExtensionToTag(name, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = name
+ });
+ operation.Tags.Add(new OpenApiTagReference(name));
base.SetTags(operation);
}
@@ -100,7 +99,7 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("operation"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
}
@@ -116,78 +115,78 @@ protected override void SetExternalDocs(OpenApiOperation operation)
if (Context.Settings.ShowExternalDocs)
{
var externalDocs = Context.Model.GetLinkRecord(TargetPath, CustomLinkRel) ??
- Context.Model.GetLinkRecord(NavigationProperty, CustomLinkRel);
-
- if (externalDocs != null)
- {
- operation.ExternalDocs = new OpenApiExternalDocs()
- {
- Description = CoreConstants.ExternalDocsDescription,
- Url = externalDocs.Href
- };
+ Context.Model.GetLinkRecord(NavigationProperty, CustomLinkRel);
+
+ if (externalDocs != null)
+ {
+ operation.ExternalDocs = new OpenApiExternalDocs()
+ {
+ Description = CoreConstants.ExternalDocsDescription,
+ Url = externalDocs.Href
+ };
}
}
- }
-
+ }
+
///
/// Retrieves the CRUD restrictions annotations for the navigation property
/// in context, given a capability annotation term.
///
/// The fully qualified restriction annotation term.
/// The restriction annotation, or null if not available.
- protected IRecord GetRestrictionAnnotation(string annotationTerm)
- {
- switch (annotationTerm)
- {
- case CapabilitiesConstants.ReadRestrictions:
- var readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(Restriction?.ReadRestrictions);
- readRestrictions ??= Restriction?.ReadRestrictions;
-
- var navPropReadRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.ReadRestrictions);
- readRestrictions?.MergePropertiesIfNull(navPropReadRestrictions);
- readRestrictions ??= navPropReadRestrictions;
-
- return readRestrictions;
- case CapabilitiesConstants.UpdateRestrictions:
- var updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- updateRestrictions?.MergePropertiesIfNull(Restriction?.UpdateRestrictions);
- updateRestrictions ??= Restriction?.UpdateRestrictions;
-
- var navPropUpdateRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.UpdateRestrictions);
- updateRestrictions?.MergePropertiesIfNull(navPropUpdateRestrictions);
- updateRestrictions ??= navPropUpdateRestrictions;
-
- return updateRestrictions;
- case CapabilitiesConstants.InsertRestrictions:
- var insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- insertRestrictions?.MergePropertiesIfNull(Restriction?.InsertRestrictions);
- insertRestrictions ??= Restriction?.InsertRestrictions;
-
- var navPropInsertRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.InsertRestrictions);
- insertRestrictions?.MergePropertiesIfNull(navPropInsertRestrictions);
- insertRestrictions ??= navPropInsertRestrictions;
-
- return insertRestrictions;
- case CapabilitiesConstants.DeleteRestrictions:
- var deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
- deleteRestrictions?.MergePropertiesIfNull(Restriction?.DeleteRestrictions);
- deleteRestrictions ??= Restriction?.DeleteRestrictions;
-
- var navPropDeleteRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.DeleteRestrictions);
- deleteRestrictions?.MergePropertiesIfNull(navPropDeleteRestrictions);
- deleteRestrictions ??= navPropDeleteRestrictions;
-
- return deleteRestrictions;
- default:
- return null;
-
- }
+ protected IRecord GetRestrictionAnnotation(string annotationTerm)
+ {
+ switch (annotationTerm)
+ {
+ case CapabilitiesConstants.ReadRestrictions:
+ var readRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ readRestrictions?.MergePropertiesIfNull(Restriction?.ReadRestrictions);
+ readRestrictions ??= Restriction?.ReadRestrictions;
+
+ var navPropReadRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.ReadRestrictions);
+ readRestrictions?.MergePropertiesIfNull(navPropReadRestrictions);
+ readRestrictions ??= navPropReadRestrictions;
+
+ return readRestrictions;
+ case CapabilitiesConstants.UpdateRestrictions:
+ var updateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ updateRestrictions?.MergePropertiesIfNull(Restriction?.UpdateRestrictions);
+ updateRestrictions ??= Restriction?.UpdateRestrictions;
+
+ var navPropUpdateRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.UpdateRestrictions);
+ updateRestrictions?.MergePropertiesIfNull(navPropUpdateRestrictions);
+ updateRestrictions ??= navPropUpdateRestrictions;
+
+ return updateRestrictions;
+ case CapabilitiesConstants.InsertRestrictions:
+ var insertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+ insertRestrictions?.MergePropertiesIfNull(Restriction?.InsertRestrictions);
+ insertRestrictions ??= Restriction?.InsertRestrictions;
+
+ var navPropInsertRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.InsertRestrictions);
+ insertRestrictions?.MergePropertiesIfNull(navPropInsertRestrictions);
+ insertRestrictions ??= navPropInsertRestrictions;
+
+ return insertRestrictions;
+ case CapabilitiesConstants.DeleteRestrictions:
+ var deleteRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
+ deleteRestrictions?.MergePropertiesIfNull(Restriction?.DeleteRestrictions);
+ deleteRestrictions ??= Restriction?.DeleteRestrictions;
+
+ var navPropDeleteRestrictions = Context.Model.GetRecord(NavigationProperty, CapabilitiesConstants.DeleteRestrictions);
+ deleteRestrictions?.MergePropertiesIfNull(navPropDeleteRestrictions);
+ deleteRestrictions ??= navPropDeleteRestrictions;
+
+ return deleteRestrictions;
+ default:
+ return null;
+
+ }
}
- protected IDictionary GetContent(OpenApiSchema schema = null, IEnumerable mediaTypes = null)
+ protected IDictionary GetContent(IOpenApiSchema schema = null, IEnumerable mediaTypes = null)
{
- schema ??= GetOpenApiSchema();
+ schema ??= GetOpenApiSchema();
var content = new Dictionary();
if (mediaTypes != null)
@@ -212,17 +211,9 @@ protected IDictionary GetContent(OpenApiSchema schema
return content;
}
- protected OpenApiSchema GetOpenApiSchema()
+ protected IOpenApiSchema GetOpenApiSchema()
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = NavigationProperty.ToEntityType().FullName()
- }
- };
+ return new OpenApiSchemaReference(NavigationProperty.ToEntityType().FullName());
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
index cebb88c9a..849178aab 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyPostOperationHandler.cs
@@ -52,14 +52,14 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
- {
- OpenApiSchema schema = null;
-
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
- {
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
- }
-
+ {
+ OpenApiSchema schema = null;
+
+ if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
+ {
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(NavigationProperty.ToEntityType(), Context.Model);
+ }
+
operation.RequestBody = new OpenApiRequestBody
{
Required = true,
@@ -72,7 +72,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
- {
+ {
OpenApiSchema schema = null;
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
@@ -94,8 +94,8 @@ protected override void SetResponses(OpenApiOperation operation)
operation.AddErrorResponses(Context.Settings, false);
base.SetResponses(operation);
- }
-
+ }
+
protected override void SetSecurity(OpenApiOperation operation)
{
if (_insertRestriction == null)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
index 8c3231e52..fae852cf3 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ODataTypeCastGetOperationHandler.cs
@@ -6,10 +6,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -62,7 +65,7 @@ private bool IsSingleElement
///
protected override void Initialize(ODataContext context, ODataPath path)
{
- // reseting the fields as we're reusing the handler
+ // resetting the fields as we're reusing the handler
singleton = null;
isKeySegment = false;
secondLastSegmentIsComplexProperty = false;
@@ -188,7 +191,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
// OperationId
if (Context.Settings.EnableOperationId)
- operation.OperationId = EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path, Context) + $".As{Utils.UpperFirstChar(TargetSchemaElement.Name)}";
+ operation.OperationId = EdmModelHelper.GenerateODataTypeCastPathOperationIdPrefix(Path, Context) + $".As{Utils.UpperFirstChar(TargetSchemaElement.Name)}-{Path.GetPathHash(Context.Settings)}";
base.SetBasicInfo(operation);
}
@@ -198,7 +201,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
if (IsSingleElement)
{
- OpenApiSchema schema = null;
+ IOpenApiSchema schema = null;
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
@@ -207,15 +210,7 @@ protected override void SetResponses(OpenApiOperation operation)
if (schema == null)
{
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = TargetSchemaElement.FullName()
- }
- };
+ schema = new OpenApiSchemaReference(TargetSchemaElement.FullName());
}
SetSingleResponse(operation, schema);
@@ -242,12 +237,11 @@ protected override void SetTags(OpenApiOperation operation)
else if ((SecondLastSegment is ODataKeySegment && !isIndexedCollValuedNavProp)
|| (SecondLastSegment is ODataNavigationSourceSegment))
{
- var entitySet = navigationSource as IEdmEntitySet;
- var singleton = navigationSource as IEdmSingleton;
+ var singletonNavigationSource = navigationSource as IEdmSingleton;
- tagName = entitySet != null
- ? entitySet.Name + "." + entitySet.EntityType.Name
- : singleton.Name + "." + singleton.EntityType.Name;
+ tagName = navigationSource is IEdmEntitySet entitySetNavigationSource
+ ? entitySetNavigationSource.Name + "." + entitySetNavigationSource.EntityType.Name
+ : singletonNavigationSource.Name + "." + singletonNavigationSource.EntityType.Name;
}
else if (SecondLastSegment is ODataComplexPropertySegment)
{
@@ -256,17 +250,14 @@ protected override void SetTags(OpenApiOperation operation)
if (tagName != null)
{
- OpenApiTag tag = new()
- {
- Name = tagName
- };
-
- if (!IsSingleElement)
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
-
- operation.Tags.Add(tag);
-
- Context.AppendTag(tag);
+ if (IsSingleElement)
+ Context.AppendTag(new OpenApiTag() { Name = tagName });
+ else
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
+ operation.Tags.Add(new OpenApiTagReference(tagName));
}
base.SetTags(operation);
@@ -305,23 +296,23 @@ protected override void SetParameters(OpenApiOperation operation)
{
if(IsSingleElement)
{
- new OpenApiParameter[] {
+ new IOpenApiParameter[] {
Context.CreateSelect(TargetPath, entitySet.EntityType) ?? Context.CreateSelect(entitySet),
Context.CreateExpand(TargetPath, entitySet.EntityType) ?? Context.CreateExpand(entitySet),
}
.Where(x => x != null)
.ToList()
- .ForEach(p => operation.Parameters.Add(p));
+ .ForEach(operation.Parameters.Add);
}
else
{
GetParametersForAnnotableOfMany(entitySet)
.Union(
- new OpenApiParameter[] {
+ [
Context.CreateOrderBy(TargetPath, entitySet.EntityType) ?? Context.CreateOrderBy(entitySet),
Context.CreateSelect(TargetPath, entitySet.EntityType) ?? Context.CreateSelect(entitySet),
Context.CreateExpand(TargetPath, entitySet.EntityType) ?? Context.CreateExpand(entitySet),
- })
+ ])
.Where(x => x != null)
.ToList()
.ForEach(p => operation.Parameters.Add(p));
@@ -338,17 +329,17 @@ protected override void SetParameters(OpenApiOperation operation)
.ForEach(p => operation.Parameters.Add(p));
}
}
- private IEnumerable GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
+ private IEnumerable GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
{
// Need to verify that TopSupported or others should be applied to navigation source.
// So, how about for the navigation property.
- return new OpenApiParameter[] {
+ return [
Context.CreateTop(annotable),
Context.CreateSkip(annotable),
Context.CreateSearch(annotable),
Context.CreateFilter(annotable),
Context.CreateCount(annotable),
- };
+ ];
}
protected override void SetSecurity(OpenApiOperation operation)
@@ -367,13 +358,13 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (Context.Settings.EnablePagination && !IsSingleElement)
{
- OpenApiObject extension = new()
+ JsonObject extension = new()
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
base.SetExtensions(operation);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
index 43cdc43cb..dd0ac2a31 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs
@@ -5,9 +5,10 @@
using System.Collections.Generic;
using System.Linq;
-using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.MicrosoftExtensions;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -30,7 +31,7 @@ internal abstract class OperationHandler : IOperationHandler
///
/// The path parameters in the path
///
- protected IList PathParameters;
+ protected IList PathParameters;
///
/// The string representation of the Edm target path for annotations.
@@ -244,14 +245,14 @@ protected static void AppendCustomParameters(OpenApiOperation operation, IList();
+ parameter.Examples = new Dictionary();
int index = 1;
foreach (var example in param.ExampleValues)
{
@@ -261,7 +262,7 @@ protected static void AppendCustomParameters(OpenApiOperation operation, IList
internal class OperationHandlerProvider : IOperationHandlerProvider
{
- private readonly IDictionary> _handlers
- = new Dictionary>{
-
- // entity set (Get/Post)
- {ODataPathKind.EntitySet, new Dictionary
+ ///
+ public IOperationHandler GetHandler(ODataPathKind pathKind, OperationType operationType)
+ {
+ return (pathKind, operationType) switch
{
- {OperationType.Get, new EntitySetGetOperationHandler() },
- {OperationType.Post, new EntitySetPostOperationHandler() }
- }},
+ // entity set (Get/Post)
+ (ODataPathKind.EntitySet, OperationType.Get) => new EntitySetGetOperationHandler(),
+ (ODataPathKind.EntitySet, OperationType.Post) => new EntitySetPostOperationHandler(),
- // entity (Get/Patch/Put/Delete)
- {ODataPathKind.Entity, new Dictionary
- {
- {OperationType.Get, new EntityGetOperationHandler() },
- {OperationType.Patch, new EntityPatchOperationHandler() },
- {OperationType.Put, new EntityPutOperationHandler() },
- {OperationType.Delete, new EntityDeleteOperationHandler() }
- }},
+ // entity (Get/Patch/Put/Delete)
+ (ODataPathKind.Entity, OperationType.Get) => new EntityGetOperationHandler(),
+ (ODataPathKind.Entity, OperationType.Patch) => new EntityPatchOperationHandler(),
+ (ODataPathKind.Entity, OperationType.Put) => new EntityPutOperationHandler(),
+ (ODataPathKind.Entity, OperationType.Delete) => new EntityDeleteOperationHandler(),
- // singleton (Get/Patch)
- {ODataPathKind.Singleton, new Dictionary
- {
- {OperationType.Get, new SingletonGetOperationHandler() },
- {OperationType.Patch, new SingletonPatchOperationHandler() }
- }},
+ // singleton (Get/Patch)
+ (ODataPathKind.Singleton, OperationType.Get) => new SingletonGetOperationHandler(),
+ (ODataPathKind.Singleton, OperationType.Patch) => new SingletonPatchOperationHandler(),
- // edm operation (Get|Post)
- {ODataPathKind.Operation, new Dictionary
- {
- {OperationType.Get, new EdmFunctionOperationHandler() },
- {OperationType.Post, new EdmActionOperationHandler() }
- }},
+ // edm operation (Get|Post)
+ (ODataPathKind.Operation, OperationType.Get) => new EdmFunctionOperationHandler(),
+ (ODataPathKind.Operation, OperationType.Post) => new EdmActionOperationHandler(),
- // edm operation import (Get|Post)
- {ODataPathKind.OperationImport, new Dictionary
- {
- {OperationType.Get, new EdmFunctionImportOperationHandler() },
- {OperationType.Post, new EdmActionImportOperationHandler() }
- }},
+ // edm operation import (Get|Post)
+ (ODataPathKind.OperationImport, OperationType.Get) => new EdmFunctionImportOperationHandler(),
+ (ODataPathKind.OperationImport, OperationType.Post) => new EdmActionImportOperationHandler(),
- // navigation property (Get/Patch/Put/Post/Delete)
- {ODataPathKind.NavigationProperty, new Dictionary
- {
- {OperationType.Get, new NavigationPropertyGetOperationHandler() },
- {OperationType.Patch, new NavigationPropertyPatchOperationHandler() },
- {OperationType.Put, new NavigationPropertyPutOperationHandler() },
- {OperationType.Post, new NavigationPropertyPostOperationHandler() },
- {OperationType.Delete, new NavigationPropertyDeleteOperationHandler() }
- }},
+ // navigation property (Get/Patch/Put/Post/Delete)
+ (ODataPathKind.NavigationProperty, OperationType.Get) => new NavigationPropertyGetOperationHandler(),
+ (ODataPathKind.NavigationProperty, OperationType.Patch) => new NavigationPropertyPatchOperationHandler(),
+ (ODataPathKind.NavigationProperty, OperationType.Put) => new NavigationPropertyPutOperationHandler(),
+ (ODataPathKind.NavigationProperty, OperationType.Post) => new NavigationPropertyPostOperationHandler(),
+ (ODataPathKind.NavigationProperty, OperationType.Delete) => new NavigationPropertyDeleteOperationHandler(),
- // navigation property ref (Get/Post/Put/Delete)
- {ODataPathKind.Ref, new Dictionary
- {
- {OperationType.Get, new RefGetOperationHandler() },
- {OperationType.Put, new RefPutOperationHandler() },
- {OperationType.Post, new RefPostOperationHandler() },
- {OperationType.Delete, new RefDeleteOperationHandler() }
- }},
+ // navigation property ref (Get/Post/Put/Delete)
+ (ODataPathKind.Ref, OperationType.Get) => new RefGetOperationHandler(),
+ (ODataPathKind.Ref, OperationType.Put) => new RefPutOperationHandler(),
+ (ODataPathKind.Ref, OperationType.Post) => new RefPostOperationHandler(),
+ (ODataPathKind.Ref, OperationType.Delete) => new RefDeleteOperationHandler(),
- // media entity operation (Get|Put|Delete)
- {ODataPathKind.MediaEntity, new Dictionary
- {
- {OperationType.Get, new MediaEntityGetOperationHandler() },
- {OperationType.Put, new MediaEntityPutOperationHandler() },
- {OperationType.Delete, new MediaEntityDeleteOperationHandler() }
- }},
+ // media entity operation (Get|Put|Delete)
+ (ODataPathKind.MediaEntity, OperationType.Get) => new MediaEntityGetOperationHandler(),
+ (ODataPathKind.MediaEntity, OperationType.Put) => new MediaEntityPutOperationHandler(),
+ (ODataPathKind.MediaEntity, OperationType.Delete) => new MediaEntityDeleteOperationHandler(),
- // $metadata operation (Get)
- {ODataPathKind.Metadata, new Dictionary
- {
- {OperationType.Get, new MetadataGetOperationHandler() }
- }},
+ // $metadata operation (Get)
- // $count operation (Get)
- {ODataPathKind.DollarCount, new Dictionary
- {
- {OperationType.Get, new DollarCountGetOperationHandler() }
- }},
+ (ODataPathKind.Metadata, OperationType.Get) => new MetadataGetOperationHandler(),
- // .../namespace.typename (cast, get)
- {ODataPathKind.TypeCast, new Dictionary
- {
- {OperationType.Get, new ODataTypeCastGetOperationHandler() },
- }},
+ // $count operation (Get)
+ (ODataPathKind.DollarCount, OperationType.Get) => new DollarCountGetOperationHandler(),
- // .../entity/propertyOfComplexType (Get/Patch/Put/Delete)
- {ODataPathKind.ComplexProperty, new Dictionary
- {
- {OperationType.Get, new ComplexPropertyGetOperationHandler() },
- {OperationType.Patch, new ComplexPropertyPatchOperationHandler() },
- {OperationType.Put, new ComplexPropertyPutOperationHandler() },
- {OperationType.Post, new ComplexPropertyPostOperationHandler() }
- }}
- };
+ // .../namespace.typename (cast, get)
+ (ODataPathKind.TypeCast, OperationType.Get) => new ODataTypeCastGetOperationHandler(),
- ///
- public IOperationHandler GetHandler(ODataPathKind pathKind, OperationType operationType)
- {
- return _handlers[pathKind][operationType];
+ // .../entity/propertyOfComplexType (Get/Patch/Put/Delete)
+ (ODataPathKind.ComplexProperty, OperationType.Get) => new ComplexPropertyGetOperationHandler(),
+ (ODataPathKind.ComplexProperty, OperationType.Patch) => new ComplexPropertyPatchOperationHandler(),
+ (ODataPathKind.ComplexProperty, OperationType.Put) => new ComplexPropertyPutOperationHandler(),
+ (ODataPathKind.ComplexProperty, OperationType.Post) => new ComplexPropertyPostOperationHandler(),
+
+ (_, _) => null,
+ };
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
index d986396b3..9fe9673c5 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefDeleteOperationHandler.cs
@@ -40,21 +40,21 @@ protected override void SetBasicInfo(OpenApiOperation operation)
// OperationId
if (Context.Settings.EnableOperationId)
{
- string prefix = "DeleteRef";
+ string prefix = "DeleteRef";
var segments = GetOperationId().Split('.').ToList();
- if (SecondLastSegmentIsKeySegment)
- {
- segments[segments.Count - 1] = Utils.ToFirstCharacterLowerCase(segments[segments.Count - 1]);
- var lastSegment = prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
- segments.Add(lastSegment);
- operation.OperationId = string.Join(".", segments);
+ if (SecondLastSegmentIsKeySegment)
+ {
+ segments[segments.Count - 1] = Utils.ToFirstCharacterLowerCase(segments[segments.Count - 1]);
+ var lastSegment = prefix + Utils.UpperFirstChar(NavigationProperty.ToEntityType().Name);
+ segments.Add(lastSegment);
+ operation.OperationId = string.Join(".", segments);
}
- else
- {
- var lastSegment = segments.LastOrDefault();
- segments[segments.Count - 1] = prefix + lastSegment;
- operation.OperationId = string.Join(".", segments);
+ else
+ {
+ var lastSegment = segments.LastOrDefault();
+ segments[segments.Count - 1] = prefix + lastSegment;
+ operation.OperationId = string.Join(".", segments);
}
}
}
@@ -71,26 +71,26 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
- });
-
- // for collection, we should have @id in query
- if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
- Path.Segments.Reverse().Skip(1).First() is ODataNavigationPropertySegment)
- {
- operation.Parameters.Add(new OpenApiParameter
- {
- Name = "@id",
- In = ParameterLocation.Query,
- Description = "The delete Uri",
- Required = true,
- Schema = new OpenApiSchema
- {
- Type = "string"
- }
- });
- }
+ });
+
+ // for collection, we should have @id in query
+ if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many &&
+ Path.Segments.Reverse().Skip(1).First() is ODataNavigationPropertySegment)
+ {
+ operation.Parameters.Add(new OpenApiParameter
+ {
+ Name = "@id",
+ In = ParameterLocation.Query,
+ Description = "The delete Uri",
+ Required = true,
+ Schema = new OpenApiSchema
+ {
+ Type = JsonSchemaType.String
+ }
+ });
+ }
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
index bf07dcf74..48d3fe7e1 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefGetOperationHandler.cs
@@ -5,9 +5,12 @@
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -59,13 +62,13 @@ protected override void SetExtensions(OpenApiOperation operation)
{
if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
{
- OpenApiObject extension = new OpenApiObject
+ JsonObject extension = new JsonObject
{
- { "nextLinkName", new OpenApiString("@odata.nextLink")},
- { "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
+ { "nextLinkName", "@odata.nextLink"},
+ { "operationName", Context.Settings.PageableOperationName}
};
- operation.Extensions.Add(Constants.xMsPageable, extension);
+ operation.Extensions.Add(Constants.xMsPageable, new OpenApiAny(extension));
}
}
@@ -81,15 +84,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
{
Context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200,
- new OpenApiResponse
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Response,
- Id = $"String{Constants.CollectionSchemaSuffix}"
- },
- }
+ new OpenApiResponseReference($"String{Constants.CollectionSchemaSuffix}")
}
};
}
@@ -98,9 +93,9 @@ protected override void SetResponses(OpenApiOperation operation)
OpenApiSchema schema = new()
{
// $ref returns string for the Uri?
- Type = "string"
+ Type = JsonSchemaType.String
};
- IDictionary links = null;
+ IDictionary links = null;
if (Context.Settings.ShowLinks)
{
string operationId = GetOperationId();
@@ -147,7 +142,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
// Need to verify that TopSupported or others should be applied to navigaiton source.
// So, how about for the navigation property.
- OpenApiParameter parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(NavigationProperty);
+ var parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(NavigationProperty);
if (parameter != null)
{
operation.Parameters.Add(parameter);
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
index bafaad2d0..7b2548ab4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs
@@ -5,6 +5,7 @@
using System.Linq;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -47,15 +48,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- operation.RequestBody = new OpenApiRequestBody
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.RequestBody,
- Id = Constants.ReferencePostRequestBodyName
- }
- };
+ operation.RequestBody = new OpenApiRequestBodyReference(Constants.ReferencePostRequestBodyName);
base.SetRequestBody(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
index 08c3aa9e9..ff2fb25ec 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs
@@ -5,6 +5,7 @@
using System.Linq;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -47,15 +48,7 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- operation.RequestBody = new OpenApiRequestBody
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.RequestBody,
- Id = Constants.ReferencePutRequestBodyName
- }
- };
+ operation.RequestBody = new OpenApiRequestBodyReference(Constants.ReferencePutRequestBodyName);
base.SetRequestBody(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
index 758c94ee8..bb39b8bfe 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs
@@ -7,6 +7,8 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -75,8 +77,8 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- OpenApiSchema schema = null;
- IDictionary links = null;
+ IOpenApiSchema schema = null;
+ IDictionary links = null;
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
@@ -89,18 +91,7 @@ protected override void SetResponses(OpenApiOperation operation)
entityKind: Singleton.ContainerElementKind.ToString(), path: Path, parameters: PathParameters);
}
- if (schema == null)
- {
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Singleton.EntityType.FullName()
- }
- };
- }
+ schema ??= new OpenApiSchemaReference(Singleton.EntityType.FullName());
operation.Responses = new OpenApiResponses
{
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
index 638f05d18..cbc8971c6 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs
@@ -6,6 +6,7 @@
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Core;
@@ -38,17 +39,14 @@ protected override void SetTags(OpenApiOperation operation)
{
// In this SDK, we use "[Singleton Name].[Singleton Entity Type Name]
// For example: "Me.User"
- OpenApiTag tag = new OpenApiTag
- {
- Name = Singleton.Name + "." + Singleton.EntityType.Name,
- };
-
- // Use an extension for TOC (Table of Content)
- tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
+ var tagName = Singleton.Name + "." + Singleton.EntityType.Name;
- operation.Tags.Add(tag);
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
- Context.AppendTag(tag);
+ operation.Tags.Add(new OpenApiTagReference(tagName));
// Call base.SetTags() at the end of this method.
base.SetTags(operation);
@@ -57,7 +55,7 @@ protected override void SetTags(OpenApiOperation operation)
///
protected override void SetExtensions(OpenApiOperation operation)
{
- operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiString("operation"));
+ operation.Extensions.Add(Constants.xMsDosOperationType, new OpenApiAny("operation"));
base.SetExtensions(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
index 03c0b47bb..51eebb81e 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs
@@ -7,6 +7,8 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -110,22 +112,11 @@ protected override void AppendCustomParameters(OpenApiOperation operation)
}
}
- private OpenApiSchema GetOpenApiSchema()
+ private IOpenApiSchema GetOpenApiSchema()
{
- if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
- {
- return EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType, Context.Model);
- }
-
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Singleton.EntityType.FullName()
- }
- };
+ return Context.Settings.EnableDerivedTypesReferencesForRequestBody ?
+ EdmModelHelper.GetDerivedTypesReferenceSchema(Singleton.EntityType, Context.Model) :
+ new OpenApiSchemaReference(Singleton.EntityType.FullName());
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/CachedPathItemHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/CachedPathItemHandlerProvider.cs
new file mode 100644
index 000000000..e978c2227
--- /dev/null
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/CachedPathItemHandlerProvider.cs
@@ -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 System.Collections.Generic;
+using Microsoft.OpenApi.OData.Common;
+using Microsoft.OpenApi.OData.Edm;
+
+namespace Microsoft.OpenApi.OData.PathItem;
+///
+/// Cached path item handler provider.
+///
+internal class CachedPathItemHandlerProvider : IPathItemHandlerProvider
+{
+ private readonly IPathItemHandlerProvider _concreteProvider;
+ private readonly Dictionary _cache = new();
+ public CachedPathItemHandlerProvider(IPathItemHandlerProvider concreteProvider)
+ {
+ Utils.CheckArgumentNull(concreteProvider, nameof(concreteProvider));
+ _concreteProvider = concreteProvider;
+ }
+ ///
+ public IPathItemHandler GetHandler(ODataPathKind pathKind)
+ {
+ if (!_cache.TryGetValue(pathKind, out IPathItemHandler handler))
+ {
+ handler = _concreteProvider.GetHandler(pathKind);
+ _cache[pathKind] = handler;
+ }
+ return handler;
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/IPathItemHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/IPathItemHandlerProvider.cs
index 7c5b509fe..b1cac2e16 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/IPathItemHandlerProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/IPathItemHandlerProvider.cs
@@ -3,6 +3,7 @@
// 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
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
index e66675f75..45f18fc5a 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs
@@ -13,6 +13,7 @@
using Microsoft.OpenApi.Any;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
+using System.Text.Json.Nodes;
namespace Microsoft.OpenApi.OData.PathItem
{
@@ -74,19 +75,19 @@ protected override void SetOperations(OpenApiPathItem item)
AddGetOperation(item, restriction);
// Update restrictions
- UpdateRestrictionsType navPropUpdateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
- navPropUpdateRestrictions?.MergePropertiesIfNull(restriction?.UpdateRestrictions);
+ UpdateRestrictionsType navPropUpdateRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.UpdateRestrictions);
+ navPropUpdateRestrictions?.MergePropertiesIfNull(restriction?.UpdateRestrictions);
navPropUpdateRestrictions ??= restriction?.UpdateRestrictions;
UpdateRestrictionsType updateRestrictions = Context.Model.GetRecord(NavigationProperty);
- navPropUpdateRestrictions?.MergePropertiesIfNull(updateRestrictions);
+ navPropUpdateRestrictions?.MergePropertiesIfNull(updateRestrictions);
navPropUpdateRestrictions ??= updateRestrictions;
// Insert restrictions
- InsertRestrictionsType navPropInsertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
- navPropInsertRestrictions?.MergePropertiesIfNull(restriction?.InsertRestrictions);
+ InsertRestrictionsType navPropInsertRestrictions = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.InsertRestrictions);
+ navPropInsertRestrictions?.MergePropertiesIfNull(restriction?.InsertRestrictions);
navPropInsertRestrictions ??= restriction?.InsertRestrictions;
InsertRestrictionsType insertRestrictions = Context.Model.GetRecord(NavigationProperty);
- navPropInsertRestrictions?.MergePropertiesIfNull(insertRestrictions);
+ navPropInsertRestrictions?.MergePropertiesIfNull(insertRestrictions);
navPropInsertRestrictions ??= insertRestrictions;
// Entity insert restrictions
@@ -161,11 +162,11 @@ protected override void SetOperations(OpenApiPathItem item)
private void AddGetOperation(OpenApiPathItem item, NavigationPropertyRestriction restriction)
{
- ReadRestrictionsType navPropReadRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
- navPropReadRestriction?.MergePropertiesIfNull(restriction?.ReadRestrictions);
+ ReadRestrictionsType navPropReadRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.ReadRestrictions);
+ navPropReadRestriction?.MergePropertiesIfNull(restriction?.ReadRestrictions);
navPropReadRestriction ??= restriction?.ReadRestrictions;
ReadRestrictionsType readRestrictions = Context.Model.GetRecord(NavigationProperty);
- navPropReadRestriction?.MergePropertiesIfNull(readRestrictions);
+ navPropReadRestriction?.MergePropertiesIfNull(readRestrictions);
navPropReadRestriction ??= readRestrictions;
ReadRestrictionsType entityReadRestriction = Context.Model.GetRecord(_navPropEntityType);
@@ -211,31 +212,31 @@ private void AddDeleteOperation(OpenApiPathItem item, NavigationPropertyRestrict
{
Debug.Assert(!LastSegmentIsRefSegment);
- DeleteRestrictionsType navPropDeleteRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
- navPropDeleteRestriction?.MergePropertiesIfNull(restriction?.DeleteRestrictions);
+ DeleteRestrictionsType navPropDeleteRestriction = Context.Model.GetRecord(TargetPath, CapabilitiesConstants.DeleteRestrictions);
+ navPropDeleteRestriction?.MergePropertiesIfNull(restriction?.DeleteRestrictions);
navPropDeleteRestriction ??= restriction?.DeleteRestrictions;
DeleteRestrictionsType insertRestrictions = Context.Model.GetRecord(NavigationProperty);
- navPropDeleteRestriction?.MergePropertiesIfNull(insertRestrictions);
- navPropDeleteRestriction ??= insertRestrictions;
-
- if (!(NavigationProperty.TargetMultiplicity() != EdmMultiplicity.Many || LastSegmentIsKeySegment))
- return;
-
- DeleteRestrictionsType entityDeleteRestriction = Context.Model.GetRecord(_navPropEntityType);
- bool isDeletable =
- (navPropDeleteRestriction == null && entityDeleteRestriction == null) ||
- ((entityDeleteRestriction?.IsDeletable ?? true) &&
- (navPropDeleteRestriction?.IsDeletable ?? true));
-
+ navPropDeleteRestriction?.MergePropertiesIfNull(insertRestrictions);
+ navPropDeleteRestriction ??= insertRestrictions;
+
+ if (!(NavigationProperty.TargetMultiplicity() != EdmMultiplicity.Many || LastSegmentIsKeySegment))
+ return;
+
+ DeleteRestrictionsType entityDeleteRestriction = Context.Model.GetRecord(_navPropEntityType);
+ bool isDeletable =
+ (navPropDeleteRestriction == null && entityDeleteRestriction == null) ||
+ ((entityDeleteRestriction?.IsDeletable ?? true) &&
+ (navPropDeleteRestriction?.IsDeletable ?? true));
+
if (NavigationProperty.ContainsTarget && isDeletable)
- {
- AddOperation(item, OperationType.Delete);
+ {
+ AddOperation(item, OperationType.Delete);
}
- else if (navPropDeleteRestriction?.Deletable ?? false)
- {
- // Add delete operation for non-contained nav. props only if explicitly set to true via annotation
- // Note: Use Deletable and NOT IsDeletable
- AddOperation(item, OperationType.Delete);
+ else if (navPropDeleteRestriction?.Deletable ?? false)
+ {
+ // Add delete operation for non-contained nav. props only if explicitly set to true via annotation
+ // Note: Use Deletable and NOT IsDeletable
+ AddOperation(item, OperationType.Delete);
}
return;
@@ -243,22 +244,22 @@ private void AddDeleteOperation(OpenApiPathItem item, NavigationPropertyRestrict
private void AddUpdateOperation(OpenApiPathItem item, UpdateRestrictionsType updateRestrictionsType)
{
- if (updateRestrictionsType?.IsUpdatable ?? true)
- {
- if (updateRestrictionsType?.IsUpdateMethodPutAndPatch == true)
- {
- AddOperation(item, OperationType.Put);
- AddOperation(item, OperationType.Patch);
- }
- else if (updateRestrictionsType?.IsUpdateMethodPut == true)
- {
- AddOperation(item, OperationType.Put);
- }
- else
- {
- AddOperation(item, OperationType.Patch);
- }
- }
+ if (updateRestrictionsType?.IsUpdatable ?? true)
+ {
+ if (updateRestrictionsType?.IsUpdateMethodPutAndPatch == true)
+ {
+ AddOperation(item, OperationType.Put);
+ AddOperation(item, OperationType.Patch);
+ }
+ else if (updateRestrictionsType?.IsUpdateMethodPut == true)
+ {
+ AddOperation(item, OperationType.Put);
+ }
+ else
+ {
+ AddOperation(item, OperationType.Patch);
+ }
+ }
}
@@ -313,15 +314,15 @@ protected override void SetExtensions(OpenApiPathItem item)
if (samePaths.Any())
{
- OpenApiArray array = new();
+ JsonArray array = new();
OpenApiConvertSettings settings = Context.Settings.Clone();
settings.EnableKeyAsSegment = Context.KeyAsSegment;
foreach (var p in samePaths)
{
- array.Add(new OpenApiString(p.GetPathItemName(settings)));
+ array.Add(p.GetPathItemName(settings));
}
- item.Extensions.Add(Constants.xMsDosGroupPath, array);
+ item.Extensions.Add(Constants.xMsDosGroupPath, new OpenApiAny(array));
}
base.SetExtensions(item);
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationPathItemHandler.cs
index f527238e7..484e8cd02 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationPathItemHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationPathItemHandler.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
@@ -83,15 +84,15 @@ protected override void SetExtensions(OpenApiPathItem item)
if (samePaths.Any())
{
- OpenApiArray array = new OpenApiArray();
+ JsonArray array = new JsonArray();
OpenApiConvertSettings settings = Context.Settings.Clone();
settings.EnableKeyAsSegment = Context.KeyAsSegment;
foreach (var p in samePaths)
{
- array.Add(new OpenApiString(p.GetPathItemName(settings)));
+ array.Add(p.GetPathItemName(settings));
}
- item.Extensions.Add(Constants.xMsDosGroupPath, array);
+ item.Extensions.Add(Constants.xMsDosGroupPath, new OpenApiAny(array));
}
base.SetExtensions(item);
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs
index 5cd00b386..914003cf2 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs
@@ -109,9 +109,9 @@ protected virtual void AddOperation(OpenApiPathItem item, OperationType operatio
return;
}
- IOperationHandlerProvider provider = Context.OperationHanderProvider;
- IOperationHandler operationHander = provider.GetHandler(Path.Kind, operationType);
- item.AddOperation(operationType, operationHander.CreateOperation(Context, Path));
+ IOperationHandlerProvider provider = Context.OperationHandlerProvider;
+ IOperationHandler operationHandler = provider.GetHandler(Path.Kind, operationType);
+ item.AddOperation(operationType, operationHandler.CreateOperation(Context, Path));
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs
index a675615c1..9815a0db7 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs
@@ -3,7 +3,6 @@
// 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
@@ -13,52 +12,49 @@ namespace Microsoft.OpenApi.OData.PathItem
///
internal class PathItemHandlerProvider : IPathItemHandlerProvider
{
- private readonly IDictionary _handlers = new Dictionary
+ ///
+ public IPathItemHandler GetHandler(ODataPathKind pathKind)
{
+ return pathKind switch {
// EntitySet
- { ODataPathKind.EntitySet, new EntitySetPathItemHandler() },
+ ODataPathKind.EntitySet => new EntitySetPathItemHandler(),
// Entity
- { ODataPathKind.Entity, new EntityPathItemHandler() },
+ ODataPathKind.Entity => new EntityPathItemHandler(),
// Singleton
- { ODataPathKind.Singleton, new SingletonPathItemHandler() },
+ ODataPathKind.Singleton => new SingletonPathItemHandler(),
// Navigation property
- { ODataPathKind.NavigationProperty, new NavigationPropertyPathItemHandler() },
+ ODataPathKind.NavigationProperty => new NavigationPropertyPathItemHandler(),
// Edm Operation
- { ODataPathKind.Operation, new OperationPathItemHandler() },
+ ODataPathKind.Operation => new OperationPathItemHandler(),
// Edm OperationImport
- { ODataPathKind.OperationImport, new OperationImportPathItemHandler() },
+ ODataPathKind.OperationImport => new OperationImportPathItemHandler(),
// Edm Ref
- { ODataPathKind.Ref, new RefPathItemHandler() },
+ ODataPathKind.Ref => new RefPathItemHandler(),
// Media Entity
- { ODataPathKind.MediaEntity, new MediaEntityPathItemHandler() },
+ ODataPathKind.MediaEntity => new MediaEntityPathItemHandler(),
// $Metadata
- { ODataPathKind.Metadata, new MetadataPathItemHandler() },
+ ODataPathKind.Metadata => new MetadataPathItemHandler(),
// $count
- { ODataPathKind.DollarCount, new DollarCountPathItemHandler() },
+ ODataPathKind.DollarCount => new DollarCountPathItemHandler(),
// ~/groups/{id}/members/microsoft.graph.user
- { ODataPathKind.TypeCast, new ODataTypeCastPathItemHandler() },
+ ODataPathKind.TypeCast => new ODataTypeCastPathItemHandler(),
// ~/users/{id}/mailboxSettings
- { ODataPathKind.ComplexProperty, new ComplexPropertyItemHandler() },
+ ODataPathKind.ComplexProperty => new ComplexPropertyItemHandler(),
// Unknown
- { ODataPathKind.Unknown, null },
- };
-
- ///
- public IPathItemHandler GetHandler(ODataPathKind pathKind)
- {
- return _handlers[pathKind];
+ _ => null,
+ };
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt
index eb93babff..96bcd04af 100644
--- a/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OpenApi.OData.Reader/PublicAPI.Unshipped.txt
@@ -70,7 +70,6 @@ override Microsoft.OpenApi.OData.Edm.ODataRefSegment.GetPathItemName(Microsoft.O
override Microsoft.OpenApi.OData.Edm.ODataStreamContentSegment.GetPathItemName(Microsoft.OpenApi.OData.OpenApiConvertSettings settings, System.Collections.Generic.HashSet parameters) -> string
override Microsoft.OpenApi.OData.Edm.ODataStreamPropertySegment.GetPathItemName(Microsoft.OpenApi.OData.OpenApiConvertSettings settings, System.Collections.Generic.HashSet parameters) -> string
override Microsoft.OpenApi.OData.Edm.ODataTypeCastSegment.GetPathItemName(Microsoft.OpenApi.OData.OpenApiConvertSettings settings, System.Collections.Generic.HashSet parameters) -> string
-static Microsoft.OpenApi.OData.Common.OpenApiOperationExtensions.AddErrorResponses(this Microsoft.OpenApi.Models.OpenApiOperation operation, Microsoft.OpenApi.OData.OpenApiConvertSettings settings, bool addNoContent = false, Microsoft.OpenApi.Models.OpenApiSchema schema = null) -> void
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.OperationTargetsMultiplePaths(this Microsoft.OData.Edm.IEdmModel model, Microsoft.OData.Edm.IEdmOperation operation) -> bool
static Microsoft.OpenApi.OData.Edm.EdmTypeExtensions.ShouldPathParameterBeQuoted(this Microsoft.OData.Edm.IEdmType edmType, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> bool
Microsoft.OpenApi.OData.Edm.IODataPathProvider
@@ -302,7 +301,6 @@ static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.FindAllBaseTypes(this Micr
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.GetAllElements(this Microsoft.OData.Edm.IEdmModel model) -> System.Collections.Generic.IEnumerable
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.IsOperationImportOverload(this Microsoft.OData.Edm.IEdmModel model, Microsoft.OData.Edm.IEdmOperationImport operationImport) -> bool
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.IsOperationOverload(this Microsoft.OData.Edm.IEdmModel model, Microsoft.OData.Edm.IEdmOperation operation) -> bool
-static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.IsUrlEscapeFunction(this Microsoft.OData.Edm.IEdmModel model, Microsoft.OData.Edm.IEdmFunction function) -> bool
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.IsUrlEscapeFunction(this Microsoft.OData.Edm.IEdmModel model, Microsoft.OData.Edm.IEdmOperation operation) -> bool
static Microsoft.OpenApi.OData.Edm.EdmModelExtensions.LoadAllNavigationSources(this Microsoft.OData.Edm.IEdmModel model) -> System.Collections.Generic.IDictionary>
static Microsoft.OpenApi.OData.Edm.ODataRefSegment.Instance -> Microsoft.OpenApi.OData.Edm.ODataRefSegment
@@ -313,4 +311,3 @@ virtual Microsoft.OpenApi.OData.Edm.ODataPathProvider.CanFilter(Microsoft.OData.
virtual Microsoft.OpenApi.OData.Edm.ODataPathProvider.GetPaths(Microsoft.OData.Edm.IEdmModel model, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> System.Collections.Generic.IEnumerable
virtual Microsoft.OpenApi.OData.Edm.ODataPathProvider.Initialize(Microsoft.OData.Edm.IEdmModel model) -> void
virtual Microsoft.OpenApi.OData.Edm.ODataSegment.EntityType.get -> Microsoft.OData.Edm.IEdmEntityType
-Microsoft.OpenApi.OData.Common.OpenApiOperationExtensions
diff --git a/src/OoasGui/MainForm.cs b/src/OoasGui/MainForm.cs
index e10bbae39..63cea0f30 100644
--- a/src/OoasGui/MainForm.cs
+++ b/src/OoasGui/MainForm.cs
@@ -27,7 +27,7 @@ public partial class MainForm : Form
{
private OpenApiFormat Format { get; set; } = OpenApiFormat.Json;
- private OpenApiSpecVersion Version { get; set; } = OpenApiSpecVersion.OpenApi3_0;
+ private OpenApiSpecVersion Version { get; set; } = OpenApiSpecVersion.OpenApi3_1;
private OpenApiConvertSettings Settings = new OpenApiConvertSettings();
@@ -202,15 +202,12 @@ private async Task ConvertAsync()
}
string openApi = null;
- await Task.Run(() =>
- {
- _document = EdmModel.ConvertToOpenApi(Settings);
- MemoryStream stream = new MemoryStream();
- _document.Serialize(stream, Version, Format);
- stream.Flush();
- stream.Position = 0;
- openApi = new StreamReader(stream).ReadToEnd();
- });
+ _document = EdmModel.ConvertToOpenApi(Settings);
+ MemoryStream stream = new MemoryStream();
+ await _document.SerializeAsync(stream, Version, Format);
+ await stream.FlushAsync();
+ stream.Position = 0;
+ openApi = await new StreamReader(stream).ReadToEndAsync();
oasRichTextBox.Text = openApi;
saveBtn.Enabled = true;
@@ -252,14 +249,9 @@ private async void saveBtn_Click(object sender, EventArgs e)
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string output = saveFileDialog.FileName;
- using (FileStream fs = File.Create(output))
- {
- await Task.Run(() =>
- {
- _document?.Serialize(fs, Version, Format);
- fs.Flush();
- });
- }
+ using FileStream fs = File.Create(output);
+ await _document?.SerializeAsync(fs, Version, Format);
+ await fs.FlushAsync();
MessageBox.Show("Saved successfully!");
}
diff --git a/src/OoasGui/OoasGui.csproj b/src/OoasGui/OoasGui.csproj
index 86d5d7051..52d080615 100644
--- a/src/OoasGui/OoasGui.csproj
+++ b/src/OoasGui/OoasGui.csproj
@@ -17,7 +17,7 @@
-
+
\ No newline at end of file
diff --git a/src/OoasUtil/ComLineProcesser.cs b/src/OoasUtil/ComLineProcesser.cs
index bea0f1d8c..9f73d63be 100644
--- a/src/OoasUtil/ComLineProcesser.cs
+++ b/src/OoasUtil/ComLineProcesser.cs
@@ -245,7 +245,7 @@ public bool Process()
if (Version == null)
{
- Version = OpenApiSpecVersion.OpenApi3_0;
+ Version = OpenApiSpecVersion.OpenApi3_1;
}
if (KeyAsSegment == null)
@@ -432,7 +432,7 @@ private bool ProcessTarget(int version)
return false;
}
- Version = version == 2 ? OpenApiSpecVersion.OpenApi2_0 : OpenApiSpecVersion.OpenApi3_0;
+ Version = version == 2 ? OpenApiSpecVersion.OpenApi2_0 : OpenApiSpecVersion.OpenApi3_1;
return true;
}
diff --git a/src/OoasUtil/OpenApiGenerator.cs b/src/OoasUtil/OpenApiGenerator.cs
index 3a9218039..e3ef89c91 100644
--- a/src/OoasUtil/OpenApiGenerator.cs
+++ b/src/OoasUtil/OpenApiGenerator.cs
@@ -60,12 +60,10 @@ public async Task GenerateAsync(CancellationToken cancellationToken = defa
this.ModifySettings();
- using (FileStream fs = File.Create(Output))
- {
- OpenApiDocument document = edmModel.ConvertToOpenApi(Settings);
- document.Serialize(fs, Settings.OpenApiSpecVersion, Format);
- await fs.FlushAsync(cancellationToken);
- }
+ using FileStream fs = File.Create(Output);
+ OpenApiDocument document = edmModel.ConvertToOpenApi(Settings);
+ await document.SerializeAsync(fs, Settings.OpenApiSpecVersion, Format, cancellationToken).ConfigureAwait(false);
+ await fs.FlushAsync(cancellationToken).ConfigureAwait(false);
}
catch(Exception e)
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs
index b142a3b31..a7d5841c3 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs
@@ -13,7 +13,6 @@
using System.IO;
using System.Xml;
using System.Collections.Generic;
-using System.Net;
using System.Text;
using Microsoft.OData.Edm.Validation;
using Xunit.Abstractions;
@@ -23,40 +22,27 @@ namespace Microsoft.OpenApi.OData.Tests
///
/// Edm model helpers
///
- public class EdmModelHelper
+ public class EdmModelHelper(ITestOutputHelper output)
{
public static IEdmModel EmptyModel { get; } = new EdmModel();
- public static IEdmModel MultipleInheritanceEdmModel { get; }
+ public static IEdmModel MultipleInheritanceEdmModel { get; } = CreateMultipleInheritanceEdmModel();
- public static IEdmModel InheritanceEdmModelAcrossReferences { get; }
+ public static IEdmModel InheritanceEdmModelAcrossReferences { get; } = CreateInheritanceEdmModelAcrossReferences();
- public static IEdmModel BasicEdmModel { get; }
+ public static IEdmModel BasicEdmModel { get; } = CreateEdmModel();
- public static IEdmModel MultipleSchemasEdmModel { get; }
+ public static IEdmModel MultipleSchemasEdmModel { get; } = LoadEdmModel("Multiple.Schema.OData.xml");
- public static IEdmModel CompositeKeyModel { get; }
+ public static IEdmModel CompositeKeyModel { get; } = CreateCompositeKeyModel();
- public static IEdmModel TripServiceModel { get; }
+ public static IEdmModel TripServiceModel { get; } = LoadEdmModel("TripService.OData.xml");
- public static IEdmModel ContractServiceModel { get; }
+ public static IEdmModel ContractServiceModel { get; } = LoadEdmModel("Contract.OData.xml");
- public static IEdmModel GraphBetaModel { get; }
+ public static IEdmModel GraphBetaModel { get; } = LoadEdmModel("Graph.Beta.OData.xml");
- public static IEdmModel ComposableFunctionsModel { get; }
-
- static EdmModelHelper()
- {
- MultipleInheritanceEdmModel = CreateMultipleInheritanceEdmModel();
- BasicEdmModel = CreateEdmModel();
- CompositeKeyModel = CreateCompositeKeyModel();
- TripServiceModel = LoadEdmModel("TripService.OData.xml");
- ContractServiceModel = LoadEdmModel("Contract.OData.xml");
- GraphBetaModel = LoadEdmModel("Graph.Beta.OData.xml");
- MultipleSchemasEdmModel = LoadEdmModel("Multiple.Schema.OData.xml");
- InheritanceEdmModelAcrossReferences = CreateInheritanceEdmModelAcrossReferences();
- ComposableFunctionsModel = LoadEdmModel("ComposableFunctions.OData.xml");
- }
+ public static IEdmModel ComposableFunctionsModel { get; } = LoadEdmModel("ComposableFunctions.OData.xml");
private static IEdmModel LoadEdmModel(string source)
{
@@ -64,7 +50,7 @@ private static IEdmModel LoadEdmModel(string source)
return CsdlReader.Parse(XElement.Parse(csdl).CreateReader());
}
- private static IEdmModel CreateMultipleInheritanceEdmModel()
+ private static EdmModel CreateMultipleInheritanceEdmModel()
{
var model = new EdmModel();
@@ -112,7 +98,7 @@ private static IEdmModel CreateMultipleInheritanceEdmModel()
horse.AddStructuralProperty("Height", EdmCoreModel.Instance.GetDecimal(false));
model.AddElement(horse);
- EdmNavigationPropertyInfo navInfo = new EdmNavigationPropertyInfo
+ EdmNavigationPropertyInfo navInfo = new()
{
Name = "Creatures",
Target = creature,
@@ -202,19 +188,17 @@ public static IEdmModel CreateInheritanceEdmModelAcrossReferences()
";
- IEdmModel model;
- IEnumerable errors;
XElement parsed = XElement.Parse(modelText);
bool result = CsdlReader.TryParse(parsed.CreateReader(),
uri => XElement.Parse(subModelText).CreateReader(),
- out model,
- out errors);
+ out var model,
+ out var _);
Assert.True(result);
return model;
}
- private static IEdmModel CreateEdmModel()
+ private static EdmModel CreateEdmModel()
{
var model = new EdmModel();
@@ -272,10 +256,10 @@ private static IEdmModel CreateEdmModel()
var entityContainer = new EdmEntityContainer("DefaultNs", "Container");
model.AddElement(entityContainer);
- EdmSingleton me = new EdmSingleton(entityContainer, "Me", person);
- EdmEntitySet people = new EdmEntitySet(entityContainer, "People", person);
- EdmEntitySet cities = new EdmEntitySet(entityContainer, "City", city);
- EdmEntitySet countriesOrRegions = new EdmEntitySet(entityContainer, "CountryOrRegion", countryOrRegion);
+ EdmSingleton me = new(entityContainer, "Me", person);
+ EdmEntitySet people = new(entityContainer, "People", person);
+ EdmEntitySet cities = new(entityContainer, "City", city);
+ EdmEntitySet countriesOrRegions = new(entityContainer, "CountryOrRegion", countryOrRegion);
people.AddNavigationTarget(navP, cities, new EdmPathExpression("HomeAddress/City"));
people.AddNavigationTarget(navP, cities, new EdmPathExpression("Addresses/City"));
people.AddNavigationTarget(navP2, countriesOrRegions,
@@ -295,7 +279,7 @@ private static IEdmModel CreateEdmModel()
return model;
}
- private static IEdmModel CreateCompositeKeyModel()
+ private static EdmModel CreateCompositeKeyModel()
{
var model = new EdmModel();
@@ -311,11 +295,7 @@ private static IEdmModel CreateCompositeKeyModel()
return model;
}
- private ITestOutputHelper _output;
- public EdmModelHelper(ITestOutputHelper output)
- {
- _output = output;
- }
+ private readonly ITestOutputHelper _output = output;
[Fact]
public void MultipleInheritanceEdmModelMetadataDocumentTest()
@@ -413,24 +393,18 @@ public void MultipleInheritanceEdmModelMetadataDocumentTest()
public static string GetCsdl(IEdmModel model)
{
- string edmx = String.Empty;
-
- using (StringWriter sw = new StringWriter())
+ using StringWriter sw = new();
+ XmlWriterSettings settings = new()
{
- XmlWriterSettings settings = new XmlWriterSettings();
- settings.Encoding = Encoding.UTF8;
- settings.Indent = true;
-
- using (XmlWriter xw = XmlWriter.Create(sw, settings))
- {
- IEnumerable errors;
- CsdlWriter.TryWriteCsdl(model, xw, CsdlTarget.OData, out errors);
- xw.Flush();
- }
+ Encoding = Encoding.UTF8,
+ Indent = true
+ };
- edmx = sw.ToString();
- }
+ using XmlWriter xw = XmlWriter.Create(sw, settings);
+ CsdlWriter.TryWriteCsdl(model, xw, CsdlTarget.OData, out var _);
+ xw.Flush();
+ string edmx = sw.ToString();
return edmx;
}
}
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs
index d26f909b6..9d22a50cd 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/EdmModelOpenApiExtensionsTest.cs
@@ -5,288 +5,182 @@
using System;
using System.IO;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
using Xunit;
using Xunit.Abstractions;
-namespace Microsoft.OpenApi.OData.Tests
+namespace Microsoft.OpenApi.OData.Tests;
+public class EdmModelOpenApiExtensionsTest(ITestOutputHelper output)
{
- public class EdmModelOpenApiExtensionsTest
- {
- private ITestOutputHelper _output;
-
- public EdmModelOpenApiExtensionsTest(ITestOutputHelper output)
- {
- _output = output;
- }
-
- [Fact]
- public void ConvertToOpenApiThrowsArgumentNullModel()
- {
- // Arrange
- IEdmModel model = null;
+ private readonly ITestOutputHelper _output = output;
- // Act & Assert
- Assert.Throws("model", () => model.ConvertToOpenApi());
- }
-
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void EmptyEdmModelToOpenApiJsonWorks(OpenApiSpecVersion specVersion)
- {
- // Arrange
- IEdmModel model = EdmModelHelper.EmptyModel;
- var openApiConvertSettings = new OpenApiConvertSettings();
- openApiConvertSettings.OpenApiSpecVersion = specVersion;
- openApiConvertSettings.IncludeAssemblyInfo = false;
-
- // Act
- string json = WriteEdmModelAsOpenApi(model, OpenApiFormat.Json, openApiConvertSettings);
- _output.WriteLine(json);
+ [Fact]
+ public void ConvertToOpenApiThrowsArgumentNullModel()
+ {
+ // Arrange
+ IEdmModel model = null;
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Empty.OpenApi.V2.json").ChangeLineBreaks(), json);
- }
- else
- {
- Assert.Equal(Resources.GetString("Empty.OpenApi.json").ChangeLineBreaks(), json);
- }
- }
+ // Act & Assert
+ Assert.Throws("model", model.ConvertToOpenApi);
+ }
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void EmptyEdmModelToOpenApiYamlWorks(OpenApiSpecVersion specVersion)
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Yaml)]
+ public async Task EmptyEdmModelToOpenApiWorks(OpenApiSpecVersion specVersion, OpenApiFormat format)
+ {
+ // Arrange
+ IEdmModel model = EdmModelHelper.EmptyModel;
+ var openApiConvertSettings = new OpenApiConvertSettings
{
- // Arrange
- IEdmModel model = EdmModelHelper.EmptyModel;
- var openApiConvertSettings = new OpenApiConvertSettings();
- openApiConvertSettings.OpenApiSpecVersion = specVersion;
- openApiConvertSettings.IncludeAssemblyInfo = false;
+ OpenApiSpecVersion = specVersion,
+ IncludeAssemblyInfo = false
+ };
- // Act
- string yaml = WriteEdmModelAsOpenApi(model, OpenApiFormat.Yaml, openApiConvertSettings);
- _output.WriteLine(yaml);
+ // Act
+ string result = await WriteEdmModelAsOpenApi(model, format, openApiConvertSettings);
+ var fileName = $"Empty.OpenApi.{GetVersion(specVersion)}{GetFormatExt(format)}";
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Empty.OpenApi.V2.yaml").ChangeLineBreaks(), yaml);
- }
- else
- {
- Assert.Equal(Resources.GetString("Empty.OpenApi.yaml").ChangeLineBreaks(), yaml);
- }
- }
+ // Assert
+ AssertDocumentsAreEqual(result, fileName, format);
+ }
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void BasicEdmModelToOpenApiJsonWorks(OpenApiSpecVersion specVersion)
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Yaml)]
+ public async Task BasicEdmModelToOpenApiWorks(OpenApiSpecVersion specVersion, OpenApiFormat format)
+ {
+ // Arrange
+ IEdmModel model = EdmModelHelper.BasicEdmModel;
+ var openApiConvertSettings = new OpenApiConvertSettings
{
- // Arrange
- IEdmModel model = EdmModelHelper.BasicEdmModel;
- var openApiConvertSettings = new OpenApiConvertSettings
- {
- OpenApiSpecVersion = specVersion,
- ShowSchemaExamples = true, // test for schema examples
- IncludeAssemblyInfo = false,
- UseStringArrayForQueryOptionsSchema = false
- };
-
- // Act
- string json = WriteEdmModelAsOpenApi(model, OpenApiFormat.Json, openApiConvertSettings);
- _output.WriteLine(json);
-
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Basic.OpenApi.V2.json").ChangeLineBreaks(), json);
- }
- else
- {
- Assert.Equal(Resources.GetString("Basic.OpenApi.json").ChangeLineBreaks(), json);
- }
- }
+ OpenApiSpecVersion = specVersion,
+ ShowSchemaExamples = true, // test for schema examples
+ IncludeAssemblyInfo = false,
+ UseStringArrayForQueryOptionsSchema = false
+ };
+
+ // Act
+ string result = await WriteEdmModelAsOpenApi(model, format, openApiConvertSettings);
+ var fileName = $"Basic.OpenApi.{GetVersion(specVersion)}{GetFormatExt(format)}";
+
+ // Assert
+ AssertDocumentsAreEqual(result, fileName, format);
+ }
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void BasicEdmModelToOpenApiYamlWorks(OpenApiSpecVersion specVersion)
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Yaml)]
+ public async Task MultipleSchemasEdmModelToOpenApiWorks(OpenApiSpecVersion specVersion, OpenApiFormat format)
+ {
+ // Arrange
+ IEdmModel model = EdmModelHelper.MultipleSchemasEdmModel;
+ var openApiConvertSettings = new OpenApiConvertSettings
{
- // Arrange
- IEdmModel model = EdmModelHelper.BasicEdmModel;
- var openApiConvertSettings = new OpenApiConvertSettings
- {
- OpenApiSpecVersion = specVersion,
- ShowSchemaExamples = true,
- IncludeAssemblyInfo = false,
- UseStringArrayForQueryOptionsSchema = false
- };
+ OpenApiSpecVersion = specVersion,
+ ShowLinks = true, // test Links
+ ShowSchemaExamples = true,
+ IncludeAssemblyInfo = false,
+ UseStringArrayForQueryOptionsSchema = false
+ };
- // Act
- string yaml = WriteEdmModelAsOpenApi(model, OpenApiFormat.Yaml, openApiConvertSettings);
- _output.WriteLine(yaml);
+ // Act
+ string result = await WriteEdmModelAsOpenApi(model, format, openApiConvertSettings);
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Basic.OpenApi.V2.yaml").ChangeLineBreaks(), yaml);
- }
- else
- {
- Assert.Equal(Resources.GetString("Basic.OpenApi.yaml").ChangeLineBreaks(), yaml);
- }
- }
-
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void MultipleSchemasEdmModelToOpenApiJsonWorks(OpenApiSpecVersion specVersion)
- {
- // Arrange
- IEdmModel model = EdmModelHelper.MultipleSchemasEdmModel;
- var openApiConvertSettings = new OpenApiConvertSettings
- {
- OpenApiSpecVersion = specVersion,
- ShowLinks = true, // test Links
- ShowSchemaExamples = true,
- IncludeAssemblyInfo = false,
- UseStringArrayForQueryOptionsSchema = false
- };
+ var fileName = $"Multiple.Schema.OpenApi.{GetVersion(specVersion)}{GetFormatExt(format)}";
- // Act
- string json = WriteEdmModelAsOpenApi(model, OpenApiFormat.Json, openApiConvertSettings);
- _output.WriteLine(json);
-
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Multiple.Schema.OpenApi.V2.json").ChangeLineBreaks(), json);
- }
- else
- {
- Assert.Equal(Resources.GetString("Multiple.Schema.OpenApi.json").ChangeLineBreaks(), json);
- }
- }
+ // Assert
+ AssertDocumentsAreEqual(result, fileName, format);
+ }
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void MultipleSchemasEdmModelToOpenApiYamlWorks(OpenApiSpecVersion specVersion)
+ [Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Json)]
+ [InlineData(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Yaml)]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1, OpenApiFormat.Yaml)]
+ public async Task TripServiceMetadataToOpenApiWorks(OpenApiSpecVersion specVersion, OpenApiFormat format)
+ {
+ // Arrange
+ IEdmModel model = EdmModelHelper.TripServiceModel;
+ OpenApiConvertSettings settings = new OpenApiConvertSettings
{
- // Arrange
- IEdmModel model = EdmModelHelper.MultipleSchemasEdmModel;
- var openApiConvertSettings = new OpenApiConvertSettings
- {
- OpenApiSpecVersion = specVersion,
- ShowLinks = true, // test Links
- ShowSchemaExamples = true,
- IncludeAssemblyInfo = false,
- UseStringArrayForQueryOptionsSchema = false
- };
-
- // Act
- string yaml = WriteEdmModelAsOpenApi(model, OpenApiFormat.Yaml, openApiConvertSettings);
- _output.WriteLine(yaml);
-
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("Multiple.Schema.OpenApi.V2.yaml").ChangeLineBreaks(), yaml);
- }
- else
- {
- Assert.Equal(Resources.GetString("Multiple.Schema.OpenApi.yaml").ChangeLineBreaks(), yaml);
- }
- }
+ EnableKeyAsSegment = true,
+ SemVerVersion = "1.0.1",
+ ServiceRoot = new Uri("http://services.odata.org/TrippinRESTierService"),
+ IEEE754Compatible = true,
+ OpenApiSpecVersion = specVersion,
+ AddSingleQuotesForStringParameters = true,
+ AddEnumDescriptionExtension = true,
+ AppendBoundOperationsOnDerivedTypeCastSegments = true,
+ IncludeAssemblyInfo = false
+ };
+ // Act
+ string result = await WriteEdmModelAsOpenApi(model, format, settings);
+
+ var fileName = $"TripService.OpenApi.{GetVersion(specVersion)}{GetFormatExt(format)}";
+
+ // Assert
+ AssertDocumentsAreEqual(result, fileName, format);
+ }
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void TripServiceMetadataToOpenApiJsonWorks(OpenApiSpecVersion specVersion)
+ private void AssertDocumentsAreEqual(string result, string fileName, OpenApiFormat format)
+ {
+ _output.WriteLine(result);
+ var expected = Resources.GetString(fileName);
+ if (format is OpenApiFormat.Json)
{
- // Arrange
- IEdmModel model = EdmModelHelper.TripServiceModel;
- OpenApiConvertSettings settings = new OpenApiConvertSettings
- {
- EnableKeyAsSegment = true,
- SemVerVersion = "1.0.1",
- ServiceRoot = new Uri("http://services.odata.org/TrippinRESTierService"),
- IEEE754Compatible = true,
- OpenApiSpecVersion = specVersion,
- AddSingleQuotesForStringParameters = true,
- AddEnumDescriptionExtension = true,
- AppendBoundOperationsOnDerivedTypeCastSegments = true,
- IncludeAssemblyInfo = false
- };
- // Act
- string json = WriteEdmModelAsOpenApi(model, OpenApiFormat.Json, settings);
- _output.WriteLine(json);
-
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("TripService.OpenApi.V2.json").ChangeLineBreaks(), json);
- }
- else
- {
- Assert.Equal(Resources.GetString("TripService.OpenApi.json").ChangeLineBreaks(), json);
- }
+ var parsedJson = JsonNode.Parse(result);
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), parsedJson));
}
-
- [Theory]
- [InlineData(OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void TripServiceMetadataToOpenApiYamlWorks(OpenApiSpecVersion specVersion)
+ else
{
- // Arrange
- IEdmModel model = EdmModelHelper.TripServiceModel;
-
- OpenApiConvertSettings settings = new OpenApiConvertSettings
- {
- EnableKeyAsSegment = true,
- SemVerVersion = "1.2.3",
- ServiceRoot = new Uri("http://services.odata.org/TrippinRESTierService"),
- IEEE754Compatible = true,
- OpenApiSpecVersion = specVersion,
- AddSingleQuotesForStringParameters = true,
- AddEnumDescriptionExtension = true,
- AppendBoundOperationsOnDerivedTypeCastSegments = true,
- IncludeAssemblyInfo = false
- };
-
- // Act
- string yaml = WriteEdmModelAsOpenApi(model, OpenApiFormat.Yaml, settings);
- _output.WriteLine(yaml);
-
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(Resources.GetString("TripService.OpenApi.V2.yaml").ChangeLineBreaks(), yaml);
- }
- else
- {
- Assert.Equal(Resources.GetString("TripService.OpenApi.yaml").ChangeLineBreaks(), yaml);
- }
+ Assert.Equal(expected.ChangeLineBreaks(), result);
}
+ }
- private static string WriteEdmModelAsOpenApi(IEdmModel model, OpenApiFormat target,
- OpenApiConvertSettings settings = null)
- {
- settings = settings ?? new OpenApiConvertSettings();
- var document = model.ConvertToOpenApi(settings);
- Assert.NotNull(document); // guard
-
- MemoryStream stream = new MemoryStream();
- document.Serialize(stream, settings.OpenApiSpecVersion, target);
- stream.Flush();
- stream.Position = 0;
- return new StreamReader(stream).ReadToEnd();
- }
+ private static string GetFormatExt(OpenApiFormat format) =>
+ format switch {
+ OpenApiFormat.Json => "json",
+ OpenApiFormat.Yaml => "yaml",
+ _ => throw new NotImplementedException()
+ };
+
+ private static string GetVersion(OpenApiSpecVersion version) =>
+ version switch {
+ OpenApiSpecVersion.OpenApi2_0 => "V2.",
+ OpenApiSpecVersion.OpenApi3_0 => string.Empty,
+ OpenApiSpecVersion.OpenApi3_1 => "V3.1.",
+ _ => throw new NotImplementedException()
+ };
+
+ private static async Task WriteEdmModelAsOpenApi(IEdmModel model, OpenApiFormat target,
+ OpenApiConvertSettings settings = null)
+ {
+ settings ??= new OpenApiConvertSettings();
+ var document = model.ConvertToOpenApi(settings);
+ Assert.NotNull(document); // guard
+
+ MemoryStream stream = new();
+ await document.SerializeAsync(stream, settings.OpenApiSpecVersion, target);
+ await stream.FlushAsync();
+ stream.Position = 0;
+ return await new StreamReader(stream).ReadToEndAsync();
}
}
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiComponentsGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiComponentsGeneratorTests.cs
index 63cd2703a..5e52da5bc 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiComponentsGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiComponentsGeneratorTests.cs
@@ -5,8 +5,10 @@
using System;
using Microsoft.OData.Edm;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
+using Moq;
using Xunit;
namespace Microsoft.OpenApi.OData.Generator.Tests
@@ -18,9 +20,12 @@ public void CreateComponentsThrowArgumentNullContext()
{
// Arrange
ODataContext context = null;
+ OpenApiDocument openApiDocument = new();
+ var mockModel = new Mock().Object;
// Act & Assert
- Assert.Throws("context", () => context.CreateComponents());
+ Assert.Throws("context", () => context.AddComponentsToDocument(openApiDocument));
+ Assert.Throws("document", () => new ODataContext(mockModel).AddComponentsToDocument(null));
}
[Fact]
@@ -29,9 +34,11 @@ public void CreateComponentsReturnsForEmptyModel()
// Arrange
IEdmModel model = EdmModelHelper.EmptyModel;
ODataContext context = new ODataContext(model);
+ OpenApiDocument openApiDocument = new();
// Act
- var components = context.CreateComponents();
+ context.AddComponentsToDocument(openApiDocument);
+ var components = openApiDocument.Components;
// Assert
Assert.NotNull(components);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiEdmTypeSchemaGeneratorTest.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiEdmTypeSchemaGeneratorTest.cs
index 9dbae3953..562cc2c1a 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiEdmTypeSchemaGeneratorTest.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiEdmTypeSchemaGeneratorTest.cs
@@ -5,9 +5,12 @@
using System;
using System.Linq;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
using Xunit;
@@ -30,7 +33,7 @@ public void CreateEdmTypeSchemaThrowArgumentNullContext()
ODataContext context = null;
// Act & Assert
- Assert.Throws("context", () => context.CreateEdmTypeSchema(edmTypeReference: null));
+ Assert.Throws("context", () => context.CreateEdmTypeSchema(edmTypeReference: null, new()));
}
[Fact]
@@ -40,13 +43,13 @@ public void CreateEdmTypeSchemaThrowArgumentNullEdmTypeReference()
ODataContext context = new ODataContext(EdmCoreModel.Instance);
// Act & Assert
- Assert.Throws("edmTypeReference", () => context.CreateEdmTypeSchema(edmTypeReference: null));
+ Assert.Throws("edmTypeReference", () => context.CreateEdmTypeSchema(edmTypeReference: null, new()));
}
[Theory]
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionComplexType(OpenApiSpecVersion specVersion)
+ public async Task CreateEdmTypeSchemaReturnSchemaForNullableCollectionComplexType(OpenApiSpecVersion specVersion)
{
// Arrange
IEdmModel model = EdmModelHelper.TripServiceModel;
@@ -59,33 +62,33 @@ public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionComplexType(Open
new EdmCollectionType(new EdmComplexTypeReference(complex, true)));
// Act
- var schema = context.CreateEdmTypeSchema(collectionType);
+ var schema = context.CreateEdmTypeSchema(collectionType, new());
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(context.Settings.OpenApiSpecVersion);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(context.Settings.OpenApiSpecVersion));
// & Assert
if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""array"",
""items"": {
""$ref"": ""#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation""
}
-}".ChangeLineBreaks(), json);
+}"), json));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""array"",
""items"": {
""$ref"": ""#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation""
}
-}".ChangeLineBreaks(), json);
+}"), json));
}
}
[Fact]
- public void CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionComplexType()
+ public async Task CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionComplexType()
{
// Arrange
IEdmModel model = EdmModelHelper.TripServiceModel;
@@ -95,21 +98,21 @@ public void CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionComplexType()
new EdmCollectionType(new EdmComplexTypeReference(complex, false)));
// Act
- var schema = context.CreateEdmTypeSchema(collectionType);
+ var schema = context.CreateEdmTypeSchema(collectionType, new());
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""array"",
""items"": {
""$ref"": ""#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation""
}
-}".ChangeLineBreaks(), json);
+}"), json));
}
[Fact]
- public void CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionPrimitiveType()
+ public async Task CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionPrimitiveType()
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
@@ -118,21 +121,21 @@ public void CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionPrimitiveType
new EdmCollectionType(EdmCoreModel.Instance.GetString(false)));
// Act
- var schema = context.CreateEdmTypeSchema(collectionType);
+ var schema = context.CreateEdmTypeSchema(collectionType, new());
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""array"",
""items"": {
""type"": ""string""
}
-}".ChangeLineBreaks(), json);
+}"), json));
}
[Fact]
- public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionPrimitiveType()
+ public async Task CreateEdmTypeSchemaReturnSchemaForNullableCollectionPrimitiveType()
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
@@ -141,12 +144,12 @@ public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionPrimitiveType()
new EdmCollectionType(EdmCoreModel.Instance.GetInt32(true)));
// Act
- var schema = context.CreateEdmTypeSchema(collectionType);
+ var schema = context.CreateEdmTypeSchema(collectionType, new());
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""array"",
""items"": {
""maximum"": 2147483647,
@@ -155,14 +158,16 @@ public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionPrimitiveType()
""format"": ""int32"",
""nullable"": true
}
-}".ChangeLineBreaks(), json);
+}"), json));
}
[Theory]
[InlineData(true, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(true, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(true, OpenApiSpecVersion.OpenApi3_1)]
[InlineData(false, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(false, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi3_1)]
public void CreateEdmTypeSchemaReturnSchemaForEnumType(bool isNullable, OpenApiSpecVersion specVersion)
{
// Arrange
@@ -175,53 +180,50 @@ public void CreateEdmTypeSchemaReturnSchemaForEnumType(bool isNullable, OpenApiS
context.Settings.OpenApiSpecVersion = specVersion;
// Act
- var schema = context.CreateEdmTypeSchema(enumTypeReference);
+ var schema = context.CreateEdmTypeSchema(enumTypeReference, new());
// & Assert
Assert.NotNull(schema);
-
-
if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
- Assert.NotNull(schema.Reference);
+ var schemaReference = Assert.IsType(schema);
Assert.Null(schema.AnyOf);
- Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
- Assert.Equal(enumType.FullTypeName(), schema.Reference.Id);
- Assert.Equal(isNullable, schema.Nullable);
+ Assert.Equal(ReferenceType.Schema, schemaReference.Reference.Type);
+ Assert.Equal(enumType.FullTypeName(), schemaReference.Reference.Id);
}
else
{
-
if (isNullable)
{
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
- Assert.Null(schema.Reference);
+ Assert.IsNotType(schema);
Assert.Equal(2, schema.AnyOf.Count);
- var anyOfRef = schema.AnyOf.FirstOrDefault();
+ var anyOfRef = Assert.IsType(schema.AnyOf.FirstOrDefault());
Assert.NotNull(anyOfRef.Reference);
Assert.Equal(ReferenceType.Schema, anyOfRef.Reference.Type);
Assert.Equal(enumType.FullTypeName(), anyOfRef.Reference.Id);
var anyOfNull = schema.AnyOf.Skip(1).FirstOrDefault();
Assert.NotNull(anyOfNull.Type);
- Assert.Equal("object", anyOfNull.Type);
- Assert.True(anyOfNull.Nullable);
+ Assert.Equal(JsonSchemaType.Null, anyOfNull.Type);
}
else
{
Assert.Null(schema.AnyOf);
- Assert.NotNull(schema.Reference);
- Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
- Assert.Equal(enumType.FullTypeName(), schema.Reference.Id);
- }
+ var schemaReference = Assert.IsType(schema);
+ Assert.Equal(ReferenceType.Schema, schemaReference.Reference.Type);
+ Assert.Equal(enumType.FullTypeName(), schemaReference.Reference.Id);
+ }
}
}
[Theory]
[InlineData(true, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(true, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(true, OpenApiSpecVersion.OpenApi3_1)]
[InlineData(false, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(false, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi3_1)]
public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenApiSpecVersion specVersion)
{
// Arrange
@@ -234,7 +236,7 @@ public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenA
context.Settings.OpenApiSpecVersion = specVersion;
// Act
- var schema = context.CreateEdmTypeSchema(complexTypeReference);
+ var schema = context.CreateEdmTypeSchema(complexTypeReference, new());
// & Assert
Assert.NotNull(schema);
@@ -242,17 +244,17 @@ public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenA
if (specVersion == OpenApiSpecVersion.OpenApi2_0 || isNullable == false)
{
Assert.Null(schema.AnyOf);
- Assert.NotNull(schema.Reference);
- Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
- Assert.Equal(complex.FullTypeName(), schema.Reference.Id);
+ var schemaReference = Assert.IsType(schema);
+ Assert.Equal(ReferenceType.Schema, schemaReference.Reference.Type);
+ Assert.Equal(complex.FullTypeName(), schemaReference.Reference.Id);
}
else
{
- Assert.Null(schema.Reference);
+ Assert.IsNotType(schema);
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
Assert.Equal(2, schema.AnyOf.Count);
- var anyOf = schema.AnyOf.FirstOrDefault();
+ var anyOf = Assert.IsType(schema.AnyOf.FirstOrDefault());
Assert.NotNull(anyOf.Reference);
Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type);
Assert.Equal(complex.FullTypeName(), anyOf.Reference.Id);
@@ -260,10 +262,12 @@ public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenA
}
[Theory]
+ [InlineData(true, OpenApiSpecVersion.OpenApi3_1)]
[InlineData(true, OpenApiSpecVersion.OpenApi3_0)]
[InlineData(true, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(false, OpenApiSpecVersion.OpenApi2_0)]
[InlineData(false, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi3_1)]
public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable, OpenApiSpecVersion specVersion)
{
// Arrange
@@ -276,31 +280,31 @@ public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable, OpenAp
context.Settings.OpenApiSpecVersion = specVersion;
// Act
- var schema = context.CreateEdmTypeSchema(entityTypeReference);
+ var schema = context.CreateEdmTypeSchema(entityTypeReference, new());
// & Assert
Assert.NotNull(schema);
- if (specVersion == OpenApiSpecVersion.OpenApi2_0 || isNullable == false)
+ if (specVersion == OpenApiSpecVersion.OpenApi2_0 || !isNullable)
{
Assert.Null(schema.AnyOf);
- Assert.NotNull(schema.Reference);
- Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
- Assert.Equal(entity.FullTypeName(), schema.Reference.Id);
+ var schemaReference = Assert.IsType(schema);
+ Assert.NotNull(schemaReference.Reference);
+ Assert.Equal(ReferenceType.Schema, schemaReference.Reference.Type);
+ Assert.Equal(entity.FullTypeName(), schemaReference.Reference.Id);
}
else
{
- Assert.Null(schema.Reference);
+ Assert.IsNotType(schema);
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
- var anyOfRef = schema.AnyOf.FirstOrDefault();
+ var anyOfRef = Assert.IsType(schema.AnyOf.FirstOrDefault());
Assert.NotNull(anyOfRef.Reference);
Assert.Equal(ReferenceType.Schema, anyOfRef.Reference.Type);
Assert.Equal(entity.FullTypeName(), anyOfRef.Reference.Id);
var anyOfNull = schema.AnyOf.Skip(1).FirstOrDefault();
Assert.NotNull(anyOfNull.Type);
- Assert.Equal("object", anyOfNull.Type);
- Assert.True(anyOfNull.Nullable);
+ Assert.Equal(JsonSchemaType.Null, anyOfNull.Type);
}
}
@@ -309,7 +313,7 @@ public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable, OpenAp
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEdmTypeSchemaReturnSchemaForString(bool isNullable)
+ public async Task CreateEdmTypeSchemaReturnSchemaForString(bool isNullable)
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
@@ -317,30 +321,30 @@ public void CreateEdmTypeSchemaReturnSchemaForString(bool isNullable)
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetString(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
if (isNullable)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""string"",
""nullable"": true
-}".ChangeLineBreaks(), json);
+}"), json));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""string""
-}".ChangeLineBreaks(), json);
+}"), json));
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEdmTypeSchemaReturnSchemaForInt32(bool isNullable)
+ public async Task CreateEdmTypeSchemaReturnSchemaForInt32(bool isNullable)
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
@@ -348,29 +352,29 @@ public void CreateEdmTypeSchemaReturnSchemaForInt32(bool isNullable)
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetInt32(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
if (isNullable)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""maximum"": 2147483647,
""minimum"": -2147483648,
""type"": ""number"",
""format"": ""int32"",
""nullable"": true
-}".ChangeLineBreaks(), json);
+}"), json));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""maximum"": 2147483647,
""minimum"": -2147483648,
""type"": ""number"",
""format"": ""int32""
-}".ChangeLineBreaks(), json);
+}"), json));
}
}
@@ -392,7 +396,7 @@ public void CreateEdmTypeSchemaReturnSchemaForDecimal(bool isNullable, bool IEEE
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetDecimal(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
// & Assert
@@ -401,19 +405,15 @@ public void CreateEdmTypeSchemaReturnSchemaForDecimal(bool isNullable, bool IEEE
Assert.Null(schema.Type);
Assert.NotNull(schema.OneOf);
Assert.Equal(2, schema.OneOf.Count);
- var numberSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("number", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(numberSchema);
- Assert.True(numberSchema.Nullable);
- var stringSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("string", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(stringSchema);
- Assert.True(stringSchema.Nullable);
- Assert.False(schema.Nullable);
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.Number | JsonSchemaType.Null));
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.String | JsonSchemaType.Null));
+ Assert.NotEqual(JsonSchemaType.Null, schema.Type & JsonSchemaType.Null);
}
else
{
- Assert.Equal("number", schema.Type);
+ Assert.Equal(JsonSchemaType.Number, schema.Type & JsonSchemaType.Number);
Assert.Null(schema.OneOf);
- Assert.Equal(isNullable, schema.Nullable);
+ Assert.Equal(isNullable, (schema.Type & JsonSchemaType.Null) is JsonSchemaType.Null);
}
}
@@ -435,7 +435,7 @@ public void CreateEdmTypeSchemaReturnSchemaForInt64(bool isNullable, bool IEEE75
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetInt64(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
// & Assert
@@ -444,26 +444,22 @@ public void CreateEdmTypeSchemaReturnSchemaForInt64(bool isNullable, bool IEEE75
Assert.Null(schema.Type);
Assert.NotNull(schema.OneOf);
Assert.Equal(2, schema.OneOf.Count);
- var numberSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("number", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(numberSchema);
- Assert.True(numberSchema.Nullable);
- var stringSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("string", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(stringSchema);
- Assert.True(stringSchema.Nullable);
- Assert.False(schema.Nullable);
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.Number | JsonSchemaType.Null));
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.String | JsonSchemaType.Null));
+ Assert.NotEqual(JsonSchemaType.Null, schema.Type & JsonSchemaType.Null);
}
else
{
- Assert.Equal("number", schema.Type);
+ Assert.Equal(JsonSchemaType.Number, schema.Type & JsonSchemaType.Number);
Assert.Null(schema.AnyOf);
- Assert.Equal(isNullable, schema.Nullable);
+ Assert.Equal(isNullable, (schema.Type & JsonSchemaType.Null) is JsonSchemaType.Null);
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEdmTypeSchemaReturnSchemaForGuid(bool isNullable)
+ public async Task CreateEdmTypeSchemaReturnSchemaForGuid(bool isNullable)
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
@@ -471,27 +467,27 @@ public void CreateEdmTypeSchemaReturnSchemaForGuid(bool isNullable)
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetGuid(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// & Assert
if (isNullable)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""pattern"": ""^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"",
""type"": ""string"",
""format"": ""uuid"",
""nullable"": true
-}".ChangeLineBreaks(), json);
+}"), json));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""pattern"": ""^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"",
""type"": ""string"",
""format"": ""uuid""
-}".ChangeLineBreaks(), json);
+}"), json));
}
}
@@ -506,22 +502,17 @@ public void CreateEdmTypeSchemaReturnSchemaForDouble(bool isNullable)
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetDouble(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
// & Assert
Assert.Null(schema.Type);
- var numberSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("number", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(numberSchema);
- Assert.True(numberSchema.Nullable);
- Assert.Equal("double", numberSchema.Format, StringComparer.OrdinalIgnoreCase);
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.Number | JsonSchemaType.Null) && x.Format.Equals("double", StringComparison.OrdinalIgnoreCase));
- var stringSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("string", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(stringSchema);
- Assert.True(stringSchema.Nullable);
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.String | JsonSchemaType.Null));
- Assert.False(schema.Nullable);
+ Assert.NotEqual(JsonSchemaType.Null, schema.Type & JsonSchemaType.Null);
Assert.Null(schema.AnyOf);
@@ -540,22 +531,17 @@ public void CreateEdmTypeSchemaReturnSchemaForSingle(bool isNullable)
IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetSingle(isNullable);
// Act
- var schema = context.CreateEdmTypeSchema(edmTypeReference);
+ var schema = context.CreateEdmTypeSchema(edmTypeReference, new());
Assert.NotNull(schema); // guard
// & Assert
Assert.Null(schema.Type);
- var numberSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("number", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(numberSchema);
- Assert.True(numberSchema.Nullable);
- Assert.Equal("float", numberSchema.Format, StringComparer.OrdinalIgnoreCase);
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.Number | JsonSchemaType.Null) && x.Format.Equals("float", StringComparison.OrdinalIgnoreCase));
+
+ Assert.Single(schema.OneOf, x => x.Type.Equals(JsonSchemaType.String | JsonSchemaType.Null));
- var stringSchema = schema.OneOf.FirstOrDefault(x => x.Type.Equals("string", StringComparison.OrdinalIgnoreCase));
- Assert.NotNull(stringSchema);
- Assert.True(stringSchema.Nullable);
-
- Assert.False(schema.Nullable);
+ Assert.NotEqual(JsonSchemaType.Null, schema.Type & JsonSchemaType.Null);
Assert.Null(schema.AnyOf);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiErrorSchemaGeneraratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiErrorSchemaGeneraratorTests.cs
index f4a761a45..6898c61ed 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiErrorSchemaGeneraratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiErrorSchemaGeneraratorTests.cs
@@ -4,6 +4,7 @@
// ------------------------------------------------------------
using Microsoft.OData.Edm;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
using Xunit;
@@ -23,7 +24,7 @@ public void AddsEmptyInnerErrorWhenNoComplexTypeIsProvided()
var schema = OpenApiErrorSchemaGenerator.CreateInnerErrorSchema(context);
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.Empty(schema.Properties);
}
[Fact]
@@ -38,7 +39,7 @@ public void AddsInnerErrorPropertiesWhenComplexTypeIsProvided()
var schema = OpenApiErrorSchemaGenerator.CreateInnerErrorSchema(context);
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.NotEmpty(schema.Properties);
Assert.Contains("Date", schema.Properties.Keys);
Assert.Contains("RequestId", schema.Properties.Keys);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiLinkGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiLinkGeneratorTests.cs
index 8110f075a..3d630d7c8 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiLinkGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiLinkGeneratorTests.cs
@@ -7,6 +7,7 @@
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -36,7 +37,7 @@ public void CreateLinksForSingleValuedNavigationProperties()
new ODataNavigationPropertySegment(navProperty));
// Act
- IDictionary links = context.CreateLinks(
+ var links = context.CreateLinks(
entityType: navProperty.ToEntityType(),
entityName: adminEntityType.Name,
entityKind: navProperty.PropertyKind.ToString(),
@@ -87,7 +88,7 @@ public void CreateLinksForCollectionValuedNavigationProperties()
new ODataNavigationPropertySegment(navProperty2));
// Act
- IDictionary links = context.CreateLinks(
+ var links = context.CreateLinks(
entityType: navProperty2.ToEntityType(),
entityName: singletonEntityType.Name,
entityKind: navProperty2.PropertyKind.ToString(),
@@ -150,7 +151,7 @@ public void CreateLinksForSingletons()
new ODataNavigationSourceSegment(singleton));
// Act
- IDictionary links = context.CreateLinks(
+ var links = context.CreateLinks(
entityType: singleton.EntityType,
entityName: singleton.Name,
entityKind: singleton.ContainerElementKind.ToString(),
@@ -205,7 +206,7 @@ public void CreateLinksForEntities()
new ODataNavigationSourceSegment(entityset),
new ODataKeySegment(entityset.EntityType));
- var parameters = new List()
+ var parameters = new List()
{
new OpenApiParameter()
{
@@ -215,13 +216,13 @@ public void CreateLinksForEntities()
Required = true,
Schema = new OpenApiSchema()
{
- Type = "string"
+ Type = JsonSchemaType.String
}
}
};
// Act
- IDictionary links = context.CreateLinks(
+ var links = context.CreateLinks(
entityType: entityset.EntityType,
entityName: entityset.Name,
entityKind: entityset.ContainerElementKind.ToString(),
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs
index 93c51417c..d819da8fc 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiParameterGeneratorTests.cs
@@ -6,6 +6,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
@@ -13,6 +15,7 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
+using Moq;
using Xunit;
namespace Microsoft.OpenApi.OData.Generator.Tests
@@ -24,20 +27,24 @@ public void CreateParametersThrowArgumentNullContext()
{
// Arrange
ODataContext context = null;
+ var mockModel = new Mock().Object;
// Act & Assert
- Assert.Throws("context", () => context.CreateParameters());
+ Assert.Throws("context", () => context.AddParametersToDocument(new()));
+ Assert.Throws("document", () => new ODataContext(mockModel).AddParametersToDocument(null));
}
[Fact]
- public void CreateParametersReturnsCreatedParameters()
+ public async Task CreateParametersReturnsCreatedParameters()
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
ODataContext context = new ODataContext(model);
+ OpenApiDocument openApiDocument = new ();
// Act
- var parameters = context.CreateParameters();
+ context.AddParametersToDocument(openApiDocument);
+ var parameters = openApiDocument.Components.Parameters;
// Assert
Assert.NotNull(parameters);
@@ -45,123 +52,98 @@ public void CreateParametersReturnsCreatedParameters()
Assert.Equal(5, parameters.Count);
Assert.Equal(new[] { "top", "skip", "count", "filter", "search" },
parameters.Select(p => p.Key));
- Assert.Collection(parameters,
- item => // $top
- {
- string json = item.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+ var expectedTop = JsonNode.Parse(@"{
""name"": ""$top"",
""in"": ""query"",
""description"": ""Show only the first n items"",
- ""style"": ""form"",
""explode"": false,
""schema"": {
""minimum"": 0,
- ""type"": ""integer""
+ ""type"": ""number"",
+ ""format"": ""int64""
},
""example"": 50
-}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
- },
- item => // $skip
- {
- string json = item.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+}");
+ var expectedSkip = JsonNode.Parse(@"{
""name"": ""$skip"",
""in"": ""query"",
""description"": ""Skip the first n items"",
- ""style"": ""form"",
""explode"": false,
""schema"": {
""minimum"": 0,
- ""type"": ""integer""
+ ""type"": ""number"",
+ ""format"": ""int64""
}
-}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
- },
- item => // $count
- {
- string json = item.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+}");
+ var expectedCount = JsonNode.Parse(@"{
""name"": ""$count"",
""in"": ""query"",
""description"": ""Include count of items"",
- ""style"": ""form"",
""explode"": false,
""schema"": {
""type"": ""boolean""
}
-}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
- },
- item => // $filter
- {
- string json = item.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+}");
+ var expectedFilter = JsonNode.Parse(@"{
""name"": ""$filter"",
""in"": ""query"",
""description"": ""Filter items by property values"",
- ""style"": ""form"",
""explode"": false,
""schema"": {
""type"": ""string""
}
-}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
- },
- item => // $search
- {
- string json = item.Value.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+}");
+ var expectedSearch = JsonNode.Parse(@"{
""name"": ""$search"",
""in"": ""query"",
""description"": ""Search items by search phrases"",
- ""style"": ""form"",
""explode"": false,
""schema"": {
""type"": ""string""
}
-}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
- });
+}");
+ var parametersAsRawJson = await Task.WhenAll(parameters.Select(p => p.Value.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0)));
+ var parametersAsJson = parametersAsRawJson.Select(x => JsonNode.Parse(x)).ToArray();
+ Assert.Contains(parametersAsJson, p => JsonNode.DeepEquals(expectedTop, p));
+ Assert.Contains(parametersAsJson, p => JsonNode.DeepEquals(expectedSkip, p));
+ Assert.Contains(parametersAsJson, p => JsonNode.DeepEquals(expectedCount, p));
+ Assert.Contains(parametersAsJson, p => JsonNode.DeepEquals(expectedFilter, p));
+ Assert.Contains(parametersAsJson, p => JsonNode.DeepEquals(expectedSearch, p));
}
[Fact]
- public void CanSeralizeAsYamlFromTheCreatedParameters()
+ public async Task CanSerializeAsYamlFromTheCreatedParameters()
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
ODataContext context = new ODataContext(model);
+ OpenApiDocument openApiDocument = new ();
// Act
- var parameters = context.CreateParameters();
+ context.AddParametersToDocument(openApiDocument);
+ var parameters = openApiDocument.Components.Parameters;
// Assert
Assert.Contains("skip", parameters.Select(p => p.Key));
var skip = parameters.First(c => c.Key == "skip").Value;
- string yaml = skip.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0);
+ string yaml = await skip.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Equal(
@"name: $skip
in: query
description: Skip the first n items
-style: form
explode: false
schema:
minimum: 0
- type: integer
+ type: number
+ format: int64
".ChangeLineBreaks(), yaml);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateKeyParametersForSingleKeyWorks(bool prefix)
+ public async Task CreateKeyParametersForSingleKeyWorks(bool prefix)
{
// Arrange
EdmModel model = new EdmModel();
@@ -182,12 +164,12 @@ public void CreateKeyParametersForSingleKeyWorks(bool prefix)
Assert.NotNull(parameters);
var parameter = Assert.Single(parameters);
- string json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected;
+ var json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ JsonNode expected;
if (prefix)
{
- expected = @"{
+ expected = JsonNode.Parse(@"{
""name"": ""Customer-Id"",
""in"": ""path"",
""description"": ""The unique identifier of Customer"",
@@ -197,11 +179,11 @@ public void CreateKeyParametersForSingleKeyWorks(bool prefix)
""nullable"": true
},
""x-ms-docs-key-type"": ""Customer""
-}";
+}");
}
else
{
- expected = @"{
+ expected = JsonNode.Parse(@"{
""name"": ""Id"",
""in"": ""path"",
""description"": ""The unique identifier of Customer"",
@@ -211,16 +193,16 @@ public void CreateKeyParametersForSingleKeyWorks(bool prefix)
""nullable"": true
},
""x-ms-docs-key-type"": ""Customer""
-}";
+}");
}
- Assert.Equal(expected.ChangeLineBreaks(), json);
+ Assert.True(JsonNode.DeepEquals(expected, json));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateKeyParametersForCompositeKeyWorks(bool prefix)
+ public async Task CreateKeyParametersForCompositeKeyWorks(bool prefix)
{
// Arrange
EdmModel model = new EdmModel();
@@ -244,8 +226,8 @@ public void CreateKeyParametersForCompositeKeyWorks(bool prefix)
// 1st
var parameter = parameters.First();
- string json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expected = @"{
+ var json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expected = JsonNode.Parse(@"{
""name"": ""firstName"",
""in"": ""path"",
""description"": ""Property in multi-part unique identifier of Customer"",
@@ -255,13 +237,13 @@ public void CreateKeyParametersForCompositeKeyWorks(bool prefix)
""nullable"": true
},
""x-ms-docs-key-type"": ""Customer""
-}";
- Assert.Equal(expected.ChangeLineBreaks(), json);
+}");
+ Assert.True(JsonNode.DeepEquals(expected, json));
// 2nd
parameter = parameters.Last();
- json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- expected = @"{
+ json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ expected = JsonNode.Parse(@"{
""name"": ""lastName"",
""in"": ""path"",
""description"": ""Property in multi-part unique identifier of Customer"",
@@ -271,12 +253,12 @@ public void CreateKeyParametersForCompositeKeyWorks(bool prefix)
""nullable"": true
},
""x-ms-docs-key-type"": ""Customer""
-}";
- Assert.Equal(expected.ChangeLineBreaks(), json);
+}");
+ Assert.True(JsonNode.DeepEquals(expected, json));
}
[Fact]
- public void CreateKeyParametersForAlternateKeyWithSinglePropertyWorks()
+ public async Task CreateKeyParametersForAlternateKeyWithSinglePropertyWorks()
{
// Arrange
EdmModel model = new();
@@ -303,8 +285,8 @@ public void CreateKeyParametersForAlternateKeyWithSinglePropertyWorks()
// Assert
Assert.NotNull(parameters);
Assert.Single(parameters);
- string json = altParameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ var json = JsonNode.Parse(await altParameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expected = JsonNode.Parse(@"{
""name"": ""AltId1"",
""in"": ""path"",
""description"": ""Alternate key of Customer"",
@@ -313,11 +295,12 @@ public void CreateKeyParametersForAlternateKeyWithSinglePropertyWorks()
""type"": ""string"",
""nullable"": true
}
-}".ChangeLineBreaks(), json);
+}");
+ Assert.True(JsonNode.DeepEquals(expected, json));
}
[Fact]
- public void CreateKeyParametersForAlternateKeyWithMultiplePropertiesWorks()
+ public async Task CreateKeyParametersForAlternateKeyWithMultiplePropertiesWorks()
{
// Arrange
EdmModel model = new();
@@ -350,8 +333,8 @@ public void CreateKeyParametersForAlternateKeyWithMultiplePropertiesWorks()
// Assert
Assert.NotNull(parameters);
Assert.Equal(2, parameters.Count);
- string json1 = altParameter1.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ var json1 = JsonNode.Parse(await altParameter1.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expected1 = JsonNode.Parse(@"{
""name"": ""AltId1"",
""in"": ""path"",
""description"": ""Property in multi-part alternate key of Customer"",
@@ -360,10 +343,11 @@ public void CreateKeyParametersForAlternateKeyWithMultiplePropertiesWorks()
""type"": ""string"",
""nullable"": true
}
-}".ChangeLineBreaks(), json1);
+}");
+ Assert.True(JsonNode.DeepEquals(expected1, json1));
- string json2 = altParameter2.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ var json2 = JsonNode.Parse(await altParameter2.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expected2 = JsonNode.Parse(@"{
""name"": ""AltId2"",
""in"": ""path"",
""description"": ""Property in multi-part alternate key of Customer"",
@@ -372,13 +356,14 @@ public void CreateKeyParametersForAlternateKeyWithMultiplePropertiesWorks()
""type"": ""string"",
""nullable"": true
}
-}".ChangeLineBreaks(), json2);
+}");
+ Assert.True(JsonNode.DeepEquals(expected2, json2));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateOrderByAndSelectAndExpandParametersWorks(bool useStringArrayForQueryOptionsSchema)
+ public async Task CreateOrderByAndSelectAndExpandParametersWorks(bool useStringArrayForQueryOptionsSchema)
{
// Arrange
IEdmModel model = GetEdmModel();
@@ -398,34 +383,34 @@ public void CreateOrderByAndSelectAndExpandParametersWorks(bool useStringArrayFo
""ID"",
""ID desc""
],";
- VerifyCreateOrderByParameter(entitySet, context, orderByItemsText);
- VerifyCreateOrderByParameter(singleton, context);
- VerifyCreateOrderByParameter(navigationProperty, context);
+ await VerifyCreateOrderByParameter(entitySet, context, orderByItemsText);
+ await VerifyCreateOrderByParameter(singleton, context);
+ await VerifyCreateOrderByParameter(navigationProperty, context);
// Select
string selectItemsText = useStringArrayForQueryOptionsSchema ? null : @"""enum"": [
""ID"",
""Addresses""
],";
- VerifyCreateSelectParameter(entitySet, context, selectItemsText);
- VerifyCreateSelectParameter(singleton, context);
- VerifyCreateSelectParameter(navigationProperty, context);
+ await VerifyCreateSelectParameter(entitySet, context, selectItemsText);
+ await VerifyCreateSelectParameter(singleton, context);
+ await VerifyCreateSelectParameter(navigationProperty, context);
// Expand
string expandItemsText = useStringArrayForQueryOptionsSchema ? null : @"""enum"": [
""*"",
""Addresses""
],";
- VerifyCreateExpandParameter(entitySet, context, expandItemsText);
+ await VerifyCreateExpandParameter(entitySet, context, expandItemsText);
string expandItemsDefaultText = useStringArrayForQueryOptionsSchema ? null : @"""enum"": [
""*""
],";
- VerifyCreateExpandParameter(singleton, context, expandItemsDefaultText);
- VerifyCreateExpandParameter(navigationProperty, context, expandItemsDefaultText);
+ await VerifyCreateExpandParameter(singleton, context, expandItemsDefaultText);
+ await VerifyCreateExpandParameter(navigationProperty, context, expandItemsDefaultText);
}
- private void VerifyCreateOrderByParameter(IEdmElement edmElement, ODataContext context, string orderByItemsText = null)
+ private static async Task VerifyCreateOrderByParameter(IEdmElement edmElement, ODataContext context, string orderByItemsText = null)
{
// Arrange & Act
OpenApiParameter parameter;
@@ -452,13 +437,11 @@ private void VerifyCreateOrderByParameter(IEdmElement edmElement, ODataContext c
// Assert
Assert.NotNull(parameter);
- string json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
-
- string expected = $@"{{
+ var json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedJson = JsonNode.Parse($@"{{
""name"": ""$orderby"",
""in"": ""query"",
""description"": ""Order items by property values"",
- ""style"": ""form"",
""explode"": false,
""schema"": {{
""uniqueItems"": true,
@@ -467,12 +450,12 @@ private void VerifyCreateOrderByParameter(IEdmElement edmElement, ODataContext c
{itemsText}
}}
}}
-}}";
+}}");
- Assert.Equal(expected.ChangeLineBreaks(), json);
+ Assert.True(JsonNode.DeepEquals(expectedJson, json));
}
- private void VerifyCreateSelectParameter(IEdmElement edmElement, ODataContext context, string selectItemsText = null)
+ private static async Task VerifyCreateSelectParameter(IEdmElement edmElement, ODataContext context, string selectItemsText = null)
{
// Arrange & Act
OpenApiParameter parameter;
@@ -499,13 +482,11 @@ private void VerifyCreateSelectParameter(IEdmElement edmElement, ODataContext co
// Assert
Assert.NotNull(parameter);
- string json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
-
- string expected = $@"{{
+ var json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedJson = JsonNode.Parse($@"{{
""name"": ""$select"",
""in"": ""query"",
""description"": ""Select properties to be returned"",
- ""style"": ""form"",
""explode"": false,
""schema"": {{
""uniqueItems"": true,
@@ -514,12 +495,11 @@ private void VerifyCreateSelectParameter(IEdmElement edmElement, ODataContext co
{itemsText}
}}
}}
-}}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
+}}");
+ Assert.True(JsonNode.DeepEquals(expectedJson, json));
}
- private void VerifyCreateExpandParameter(IEdmElement edmElement, ODataContext context, string expandItemsText)
+ private static async Task VerifyCreateExpandParameter(IEdmElement edmElement, ODataContext context, string expandItemsText)
{
// Arrange & Act
OpenApiParameter parameter;
@@ -541,15 +521,13 @@ private void VerifyCreateExpandParameter(IEdmElement edmElement, ODataContext co
// Assert
Assert.NotNull(parameter);
- string json = parameter.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
-
- string expected = expandItemsText == null
+ var json = JsonNode.Parse(await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedJson = expandItemsText == null
?
$@"{{
""name"": ""$expand"",
""in"": ""query"",
""description"": ""Expand related entities"",
- ""style"": ""form"",
""explode"": false,
""schema"": {{
""uniqueItems"": true,
@@ -564,7 +542,6 @@ private void VerifyCreateExpandParameter(IEdmElement edmElement, ODataContext co
""name"": ""$expand"",
""in"": ""query"",
""description"": ""Expand related entities"",
- ""style"": ""form"",
""explode"": false,
""schema"": {{
""uniqueItems"": true,
@@ -575,12 +552,12 @@ private void VerifyCreateExpandParameter(IEdmElement edmElement, ODataContext co
}}
}}
}}";
-
- Assert.Equal(expected.ChangeLineBreaks(), json);
+ var expectedJsonNode = JsonNode.Parse(expectedJson);
+ Assert.True(JsonNode.DeepEquals(expectedJsonNode, json));
}
[Fact]
- public void CreateParametersWorks()
+ public async Task CreateParametersWorks()
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -598,23 +575,23 @@ public void CreateParametersWorks()
Assert.NotNull(function3);
// Act
- IList parameters1 = context.CreateParameters(function1);
- IList parameters2 = context.CreateParameters(function2);
- IList parameters3 = context.CreateParameters(function3);
+ var parameters1 = context.CreateParameters(function1);
+ var parameters2 = context.CreateParameters(function2);
+ var parameters3 = context.CreateParameters(function3);
// Assert
Assert.NotNull(parameters1);
- OpenApiParameter parameter1 = Assert.Single(parameters1);
+ var parameter1 = Assert.Single(parameters1);
Assert.NotNull(parameters2);
- OpenApiParameter parameter2 = Assert.Single(parameters2);
+ var parameter2 = Assert.Single(parameters2);
Assert.NotNull(parameters3);
Assert.Equal(4, parameters3.Count);
- OpenApiParameter parameter3 = parameters3.First();
+ var parameter3 = parameters3.First();
- string json1 = parameter1.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expectedPayload1 = $@"{{
+ var json1 = JsonNode.Parse(await parameter1.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedPayload1 = JsonNode.Parse($@"{{
""name"": ""ids"",
""in"": ""path"",
""description"": ""The URL-encoded JSON object"",
@@ -629,10 +606,11 @@ public void CreateParametersWorks()
}}
}}
}}
-}}";
+}}");
+ Assert.True(JsonNode.DeepEquals(expectedPayload1, json1));
- string json2 = parameter2.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expectedPayload2 = $@"{{
+ var json2 = JsonNode.Parse(await parameter2.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedPayload2 = JsonNode.Parse($@"{{
""name"": ""resource"",
""in"": ""path"",
""required"": true,
@@ -640,21 +618,19 @@ public void CreateParametersWorks()
""type"": ""string"",
""nullable"": true
}}
-}}";
+}}");
+ Assert.True(JsonNode.DeepEquals(expectedPayload2, json2));
- string json3 = parameter3.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- string expectedPayload3 = $@"{{
+ var json3 = JsonNode.Parse(await parameter3.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
+ var expectedPayload3 = JsonNode.Parse($@"{{
""name"": ""directoryScopeId"",
""in"": ""query"",
""schema"": {{
""type"": ""string"",
""nullable"": true
}}
-}}";
-
- Assert.Equal(expectedPayload1.ChangeLineBreaks(), json1);
- Assert.Equal(expectedPayload2.ChangeLineBreaks(), json2);
- Assert.Equal(expectedPayload3.ChangeLineBreaks(), json3);
+}}");
+ Assert.True(JsonNode.DeepEquals(expectedPayload3, json3));
}
public static IEdmModel GetEdmModel()
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs
index 134befc9a..187c36bd5 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathItemGeneratorTests.cs
@@ -9,6 +9,7 @@
using Microsoft.OData.Edm.Csdl;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OData.Edm.Vocabularies.Community.V1;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
@@ -22,10 +23,11 @@ public class OpenApiPathItemGeneratorTest
public void CreatePathItemsThrowArgumentNullContext()
{
// Arrange
+ OpenApiDocument openApiDocument = new();
ODataContext context = null;
// Act & Assert
- Assert.Throws("context", () => context.CreatePathItems());
+ Assert.Throws("context", () => context.AddPathItemsToDocument(openApiDocument));
}
[Fact]
@@ -33,10 +35,12 @@ public void CreatePathItemsReturnsForEmptyModel()
{
// Arrange
IEdmModel model = EdmModelHelper.EmptyModel;
+ OpenApiDocument openApiDocument = new();
ODataContext context = new ODataContext(model);
// Act
- var pathItems = context.CreatePathItems();
+ context.AddPathItemsToDocument(openApiDocument);
+ var pathItems = openApiDocument.Paths;
// Assert
Assert.NotNull(pathItems);
@@ -50,6 +54,7 @@ public void CreatePathItemsReturnsForBasicModel(bool useAnnotationToGeneratePath
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new OpenApiConvertSettings
{
EnableKeyAsSegment = true,
@@ -58,7 +63,8 @@ public void CreatePathItemsReturnsForBasicModel(bool useAnnotationToGeneratePath
ODataContext context = new ODataContext(model, settings);
// Act
- var pathItems = context.CreatePathItems();
+ context.AddPathItemsToDocument(openApiDocument);
+ var pathItems = openApiDocument.Paths;
// Assert
Assert.NotNull(pathItems);
@@ -115,6 +121,7 @@ public void CreatePathItemsReturnsForEscapeFunctionModel(bool enableEscaped, boo
{
// Arrange
EdmModel model = new EdmModel();
+ OpenApiDocument openApiDocument = new();
EdmEntityType customer = new EdmEntityType("NS", "Customer");
customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
model.AddElement(customer);
@@ -144,7 +151,8 @@ public void CreatePathItemsReturnsForEscapeFunctionModel(bool enableEscaped, boo
ODataContext context = new ODataContext(model, settings);
// Act
- var pathItems = context.CreatePathItems();
+ context.AddPathItemsToDocument(openApiDocument);
+ var pathItems = openApiDocument.Paths;
// Assert
Assert.NotNull(pathItems);
@@ -161,6 +169,7 @@ public void CreatePathItemsDoesNotAddPathItemEntryForPathItemsWithNoOperations()
{
// Arrange
EdmModel model = new();
+ OpenApiDocument openApiDocument = new();
EdmEntityType customer = new("NS", "Customer");
customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
model.AddElement(customer);
@@ -199,7 +208,8 @@ public void CreatePathItemsDoesNotAddPathItemEntryForPathItemsWithNoOperations()
ODataContext context = new(model);
// Act
- var pathItems = context.CreatePathItems();
+ context.AddPathItemsToDocument(openApiDocument);
+ var pathItems = openApiDocument.Paths;
// Assert
Assert.NotNull(pathItems);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathsGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathsGeneratorTests.cs
index d643dc089..f658bfdac 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathsGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiPathsGeneratorTests.cs
@@ -5,24 +5,27 @@
using System;
using Microsoft.OData.Edm;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
+using Moq;
using Xunit;
namespace Microsoft.OpenApi.OData.Generator.Tests
{
public class OpenApiPathsGeneratorTest
{
- private OpenApiConvertSettings _settings = new OpenApiConvertSettings();
-
[Fact]
public void CreatePathsThrowArgumentNullContext()
{
// Arrange
+ OpenApiDocument openApiDocument = new();
ODataContext context = null;
+ var mockModel = new Mock().Object;
// Act & Assert
- Assert.Throws("context", () => context.CreatePaths());
+ Assert.Throws("context", () => context.AddPathsToDocument(openApiDocument));
+ Assert.Throws("document", () => new ODataContext(mockModel).AddPathsToDocument(null));
}
[Fact]
@@ -30,10 +33,12 @@ public void CreatePathsReturnsForEmptyModel()
{
// Arrange
IEdmModel model = EdmModelHelper.EmptyModel;
+ OpenApiDocument openApiDocument = new();
ODataContext context = new ODataContext(model);
// Act
- var paths = context.CreatePaths();
+ context.AddPathsToDocument(openApiDocument);
+ var paths = openApiDocument.Paths;
// Assert
Assert.NotNull(paths);
@@ -47,6 +52,7 @@ public void CreatePathsReturnsForBasicModel(bool useAnnotationToGeneratePath, in
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new OpenApiConvertSettings
{
EnableKeyAsSegment = true,
@@ -55,7 +61,8 @@ public void CreatePathsReturnsForBasicModel(bool useAnnotationToGeneratePath, in
ODataContext context = new ODataContext(model, settings);
// Act
- var paths = context.CreatePaths();
+ context.AddPathsToDocument(openApiDocument);
+ var paths = openApiDocument.Paths;
// Assert
Assert.NotNull(paths);
@@ -106,6 +113,7 @@ public void CreatePathsReturnsForBasicModelWithPrefix(bool useAnnotationToGenera
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new OpenApiConvertSettings
{
EnableKeyAsSegment = true,
@@ -115,7 +123,8 @@ public void CreatePathsReturnsForBasicModelWithPrefix(bool useAnnotationToGenera
ODataContext context = new ODataContext(model, settings);
// Act
- var paths = context.CreatePaths();
+ context.AddPathsToDocument(openApiDocument);
+ var paths = openApiDocument.Paths;
// Assert
Assert.NotNull(paths);
@@ -164,6 +173,7 @@ public void CreatePathsReturnsForContractModelWithHierarhicalClass()
{
// Arrange
IEdmModel model = EdmModelHelper.ContractServiceModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new OpenApiConvertSettings
{
EnableKeyAsSegment = true,
@@ -172,7 +182,8 @@ public void CreatePathsReturnsForContractModelWithHierarhicalClass()
ODataContext context = new ODataContext(model, settings);
// Act
- var paths = context.CreatePaths();
+ context.AddPathsToDocument(openApiDocument);
+ var paths = openApiDocument.Paths;
// Assert
Assert.NotNull(paths);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs
index 6abc39ee7..acc14c881 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiRequestBodyGeneratorTests.cs
@@ -5,8 +5,12 @@
using System;
using System.Linq;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -87,15 +91,15 @@ public void CreateRequestBodyForActionImportReturnCorrectRequestBody()
Assert.NotNull(content.Value.Schema);
var schema = content.Value.Schema;
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.NotNull(schema.Properties);
var parameter = Assert.Single(schema.Properties);
Assert.Equal("param", parameter.Key);
- Assert.Equal("string", parameter.Value.Type);
+ Assert.Equal(JsonSchemaType.String | JsonSchemaType.Null, parameter.Value.Type);
}
[Fact]
- public void CanSerializeAsJsonFromTheCreatedRequestBody()
+ public async Task CanSerializeAsJsonFromTheCreatedRequestBody()
{
// Arrange
ODataContext context = new ODataContext(_model);
@@ -104,9 +108,8 @@ public void CanSerializeAsJsonFromTheCreatedRequestBody()
var requestBody = context.CreateRequestBody(_actionImport);
// Assert
- string json = requestBody.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
-
- Assert.Equal(@"{
+ string json = await requestBody.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ var expectedJson = @"{
""description"": ""Action parameters"",
""content"": {
""application/json"": {
@@ -122,7 +125,12 @@ public void CanSerializeAsJsonFromTheCreatedRequestBody()
}
},
""required"": true
-}".ChangeLineBreaks(), json);
+}";
+
+ var actualJsonNode = JsonNode.Parse(json);
+ var expectedJsonNode = JsonNode.Parse(expectedJson);
+
+ Assert.True(JsonNode.DeepEquals(actualJsonNode, expectedJsonNode));
}
[Fact]
@@ -144,11 +152,11 @@ public void CreateRequestBodyForActionReturnCorrectRequestBody()
Assert.NotNull(content.Value.Schema);
var schema = content.Value.Schema;
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.NotNull(schema.Properties);
var parameter = Assert.Single(schema.Properties);
Assert.Equal("param", parameter.Key);
- Assert.Equal("string", parameter.Value.Type);
+ Assert.Equal(JsonSchemaType.String | JsonSchemaType.Null, parameter.Value.Type);
}
[Fact]
@@ -156,15 +164,18 @@ public void CreateRefRequestBodies()
{
// Arrange
ODataContext context = new ODataContext(_model);
+ OpenApiDocument openApiDocument = new OpenApiDocument();
// Act
- var requestBodies = context.CreateRequestBodies();
- requestBodies.TryGetValue(Common.Constants.ReferencePostRequestBodyName, out Models.OpenApiRequestBody refPostBody);
+ context.AddRequestBodiesToDocument(openApiDocument);
+ var requestBodies = openApiDocument.Components.RequestBodies;
+ requestBodies.TryGetValue(Common.Constants.ReferencePostRequestBodyName, out var refPostBody);
// Assert
Assert.NotNull(refPostBody);
Assert.Equal("New navigation property ref value", refPostBody.Description);
- Assert.Equal(Common.Constants.ReferenceCreateSchemaName, refPostBody.Content.First().Value.Schema.Reference.Id);
+ var schemaReference = Assert.IsType(refPostBody.Content.First().Value.Schema);
+ Assert.Equal(Common.Constants.ReferenceCreateSchemaName, schemaReference.Reference.Id);
}
}
}
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiResponseGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiResponseGeneratorTests.cs
index 857b2740e..d45a3001e 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiResponseGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiResponseGeneratorTests.cs
@@ -11,6 +11,10 @@
using Microsoft.OpenApi.Models;
using Xunit;
using Microsoft.OpenApi.OData.Edm;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using Moq;
+using Microsoft.OpenApi.Models.References;
namespace Microsoft.OpenApi.OData.Generator.Tests
{
@@ -46,9 +50,11 @@ public void CreateResponsesThrowArgumentNullContext()
{
// Arrange
ODataContext context = null;
+ var mockModel = new Mock().Object;
// Act & Assert
- Assert.Throws("context", () => context.CreateResponses());
+ Assert.Throws("context", () => context.AddResponsesToDocument(new()));
+ Assert.Throws("document", () => new ODataContext(mockModel).AddResponsesToDocument(null));
}
[Fact]
@@ -62,15 +68,19 @@ public void CreatesCollectionResponses()
EnablePagination = true,
};
ODataContext context = new(model, settings);
+ OpenApiDocument document = new();
// Act & Assert
- var responses = context.CreateResponses();
+ context.AddResponsesToDocument(document);
+ var responses = document.Components.Responses;
var flightCollectionResponse = responses["Microsoft.OData.Service.Sample.TrippinInMemory.Models.FlightCollectionResponse"];
var stringCollectionResponse = responses["StringCollectionResponse"];
- Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.FlightCollectionResponse", flightCollectionResponse.Content["application/json"].Schema.Reference.Id);
- Assert.Equal("StringCollectionResponse", stringCollectionResponse.Content["application/json"].Schema.Reference.Id);
+ var flightCollectionResponseSchemaReference = Assert.IsType(flightCollectionResponse.Content["application/json"].Schema);
+ Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.FlightCollectionResponse", flightCollectionResponseSchemaReference.Reference.Id);
+ var stringCollectionResponseSchemaReference = Assert.IsType(stringCollectionResponse.Content["application/json"].Schema);
+ Assert.Equal("StringCollectionResponse", stringCollectionResponseSchemaReference.Reference.Id);
}
[Fact]
@@ -79,9 +89,11 @@ public void CreateResponsesReturnsCreatedResponses()
// Arrange
IEdmModel model = EdmCoreModel.Instance;
ODataContext context = new ODataContext(model);
+ OpenApiDocument document = new();
// Act
- var responses = context.CreateResponses();
+ context.AddResponsesToDocument(document);
+ var responses = document.Components.Responses;
// Assert
Assert.NotNull(responses);
@@ -94,21 +106,23 @@ public void CreateResponsesReturnsCreatedResponses()
}
[Fact]
- public void CanSerializeAsJsonFromTheCreatedResponses()
+ public async Task CanSerializeAsJsonFromTheCreatedResponses()
{
// Arrange
IEdmModel model = EdmCoreModel.Instance;
ODataContext context = new ODataContext(model);
+ OpenApiDocument document = new();
// Act
- var responses = context.CreateResponses();
+ context.AddResponsesToDocument(document);
+ var responses = document.Components.Responses;
// Assert
var response = responses["error"];
Assert.NotNull(response);
- string json = response.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await response.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ var expectedJson = @"{
""description"": ""error"",
""content"": {
""application/json"": {
@@ -117,7 +131,10 @@ public void CanSerializeAsJsonFromTheCreatedResponses()
}
}
}
-}".ChangeLineBreaks(), json);
+}";
+ var expectedJsonNode = JsonNode.Parse(expectedJson);
+ var actualJsonNode = JsonNode.Parse(json);
+ Assert.True(JsonNode.DeepEquals(expectedJsonNode, actualJsonNode));
}
[Fact]
@@ -158,73 +175,72 @@ public void CreateResponseForOperationThrowArgumentNullOperation()
// Act & Assert
Assert.Throws("operation", () => context.CreateResponses(operation: null));
- }
-
- [Theory]
- [InlineData(true, OpenApiSpecVersion.OpenApi3_0)]
- [InlineData(false, OpenApiSpecVersion.OpenApi3_0)]
- [InlineData(true, OpenApiSpecVersion.OpenApi2_0)]
- [InlineData(false, OpenApiSpecVersion.OpenApi2_0)]
- public void CreateResponseForEdmFunctionReturnCorrectResponses(bool isFunctionImport, OpenApiSpecVersion specVersion)
- {
- // Arrange
- string operationName = "GetPersonWithMostFriends";
- IEdmModel model = EdmModelHelper.TripServiceModel;
- ODataContext context = new ODataContext(model);
-
- context.Settings.OpenApiSpecVersion = specVersion;
-
- // Act
- OpenApiResponses responses;
- if (isFunctionImport)
- {
- IEdmOperationImport operationImport = model.EntityContainer.OperationImports().First(o => o.Name == operationName);
- Assert.NotNull(operationImport); // guard
- ODataPath path = new ODataPath(new ODataOperationImportSegment(operationImport));
- responses = context.CreateResponses(operationImport);
- }
- else
- {
- IEdmOperation operation = model.SchemaElements.OfType().First(o => o.Name == operationName);
- Assert.NotNull(operation); // guard
- ODataPath path = new ODataPath(new ODataOperationSegment(operation));
- responses = context.CreateResponses(operation);
- }
-
- // Assert
- Assert.NotNull(responses);
- Assert.NotEmpty(responses);
- Assert.Equal(2, responses.Count);
- Assert.Equal(new string[] { "200", "default" }, responses.Select(r => r.Key));
-
- OpenApiResponse response = responses["200"];
- Assert.NotNull(response.Content);
- OpenApiMediaType mediaType = response.Content["application/json"];
-
- // openApi version 2 should not use AnyOf
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.NotNull(mediaType.Schema);
- Assert.Null(mediaType.Schema.AnyOf);
- Assert.NotNull(mediaType.Schema.Reference);
- Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", mediaType.Schema.Reference.Id);
- Assert.True(mediaType.Schema.Nullable);
- }
- else
- {
- Assert.NotNull(mediaType.Schema);
- Assert.Null(mediaType.Schema.Reference);
- Assert.NotNull(mediaType.Schema.AnyOf);
- Assert.Equal(2, mediaType.Schema.AnyOf.Count);
- var anyOfRef = mediaType.Schema.AnyOf.FirstOrDefault();
- Assert.NotNull(anyOfRef);
- Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOfRef.Reference.Id);
- var anyOfNull = mediaType.Schema.AnyOf.Skip(1).FirstOrDefault();
- Assert.NotNull(anyOfNull.Type);
- Assert.Equal("object", anyOfNull.Type);
- Assert.True(anyOfNull.Nullable);
-
- }
+ }
+
+ [Theory]
+ [InlineData(true, OpenApiSpecVersion.OpenApi3_1)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi3_1)]
+ [InlineData(true, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi3_0)]
+ [InlineData(true, OpenApiSpecVersion.OpenApi2_0)]
+ [InlineData(false, OpenApiSpecVersion.OpenApi2_0)]
+ public void CreateResponseForEdmFunctionReturnCorrectResponses(bool isFunctionImport, OpenApiSpecVersion specVersion)
+ {
+ // Arrange
+ string operationName = "GetPersonWithMostFriends";
+ IEdmModel model = EdmModelHelper.TripServiceModel;
+ ODataContext context = new ODataContext(model);
+
+ context.Settings.OpenApiSpecVersion = specVersion;
+
+ // Act
+ OpenApiResponses responses;
+ if (isFunctionImport)
+ {
+ IEdmOperationImport operationImport = model.EntityContainer.OperationImports().First(o => o.Name == operationName);
+ Assert.NotNull(operationImport); // guard
+ ODataPath path = new ODataPath(new ODataOperationImportSegment(operationImport));
+ responses = context.CreateResponses(operationImport);
+ }
+ else
+ {
+ IEdmOperation operation = model.SchemaElements.OfType().First(o => o.Name == operationName);
+ Assert.NotNull(operation); // guard
+ ODataPath path = new ODataPath(new ODataOperationSegment(operation));
+ responses = context.CreateResponses(operation);
+ }
+
+ // Assert
+ Assert.NotNull(responses);
+ Assert.NotEmpty(responses);
+ Assert.Equal(2, responses.Count);
+ Assert.Equal(new string[] { "200", "default" }, responses.Select(r => r.Key));
+
+ var response = responses["200"];
+ Assert.NotNull(response.Content);
+ OpenApiMediaType mediaType = response.Content["application/json"];
+// openApi version 2 should not use AnyOf
+ if (specVersion == OpenApiSpecVersion.OpenApi2_0)
+ {
+ Assert.NotNull(mediaType.Schema);
+ Assert.Null(mediaType.Schema.AnyOf);
+ var mediaTypeSchemaReference = Assert.IsType(mediaType.Schema);
+ Assert.NotNull(mediaTypeSchemaReference.Reference);
+ Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", mediaTypeSchemaReference.Reference.Id);
+ }
+ else
+ {
+ Assert.NotNull(mediaType.Schema);
+ Assert.IsNotType(mediaType.Schema);
+ Assert.NotNull(mediaType.Schema.AnyOf);
+ Assert.Equal(2, mediaType.Schema.AnyOf.Count);
+ var anyOfRef = Assert.IsType(mediaType.Schema.AnyOf.FirstOrDefault());
+ Assert.NotNull(anyOfRef);
+ Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOfRef.Reference.Id);
+ var anyOfNull = mediaType.Schema.AnyOf.Skip(1).FirstOrDefault();
+ Assert.NotNull(anyOfNull.Type);
+ Assert.Equal(JsonSchemaType.Null, anyOfNull.Type);
+ }
}
[Fact]
@@ -252,7 +268,7 @@ public void CreateResponseForEdmFunctionOfStreamReturnTypeReturnsCorrectResponse
Assert.Equal(2, responses1.Count);
Assert.Equal(new string[] { "200", "default" }, responses1.Select(r => r.Key));
- OpenApiResponse response = responses1["200"];
+ var response = responses1["200"];
Assert.NotNull(response.Content);
Assert.Equal("application/octet-stream", response.Content.First().Key);
@@ -338,7 +354,7 @@ public void CreateResponseForEdmActionWhenErrorResponsesAsDefaultIsSet(string ac
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateResponseForDeltaEdmFunctionReturnCorrectResponses(bool enableOdataAnnotationRef)
+ public async Task CreateResponseForDeltaEdmFunctionReturnCorrectResponses(bool enableOdataAnnotationRef)
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -353,14 +369,14 @@ public void CreateResponseForDeltaEdmFunctionReturnCorrectResponses(bool enableO
o.Parameters.First().Type.FullName() == "Collection(microsoft.graph.application)");
Assert.NotNull(operation); // guard
OpenApiResponses responses = context.CreateResponses(operation);
- string json = responses.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await responses.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(responses);
Assert.NotEmpty(responses);
if (enableOdataAnnotationRef)
{
- Assert.Equal(@"{
+ var expectedJson = @"{
""200"": {
""description"": ""Success"",
""content"": {
@@ -391,11 +407,14 @@ public void CreateResponseForDeltaEdmFunctionReturnCorrectResponses(bool enableO
""default"": {
""$ref"": ""#/components/responses/error""
}
-}".ChangeLineBreaks(), json);
+}";
+ var expectedJsonNode = JsonNode.Parse(expectedJson);
+ var actualJsonNode = JsonNode.Parse(json);
+ Assert.True(JsonNode.DeepEquals(expectedJsonNode, actualJsonNode));
}
else
{
- Assert.Equal(@"{
+ var expectedJson = @"{
""200"": {
""description"": ""Success"",
""content"": {
@@ -426,7 +445,10 @@ public void CreateResponseForDeltaEdmFunctionReturnCorrectResponses(bool enableO
""default"": {
""$ref"": ""#/components/responses/error""
}
-}".ChangeLineBreaks(), json);
+}";
+ var expectedJsonNode = JsonNode.Parse(expectedJson);
+ var actualJsonNode = JsonNode.Parse(json);
+ Assert.True(JsonNode.DeepEquals(expectedJsonNode, actualJsonNode));
}
}
}
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs
index de5a38643..b5637cf48 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSchemaGeneratorTests.cs
@@ -5,10 +5,12 @@
using System;
using System.Linq;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
-using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
@@ -19,7 +21,7 @@ namespace Microsoft.OpenApi.OData.Tests
{
public class OpenApiSchemaGeneratorTest
{
- private ITestOutputHelper _output;
+ private readonly ITestOutputHelper _output;
public OpenApiSchemaGeneratorTest(ITestOutputHelper output)
{
_output = output;
@@ -30,9 +32,10 @@ public void CreateSchemasThrowArgumentNullContext()
{
// Arrange
ODataContext context = null;
+ OpenApiDocument openApiDocument = new();
// Act & Assert
- Assert.Throws("context", () => context.CreateSchemas());
+ Assert.Throws("context", () => context.AddSchemasToDocument(openApiDocument));
}
[Theory]
@@ -44,6 +47,7 @@ public void CreatesCollectionResponseSchema(bool enablePagination, bool enableCo
{
// Arrange
IEdmModel model = EdmModelHelper.TripServiceModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new()
{
EnableOperationId = true,
@@ -53,32 +57,35 @@ public void CreatesCollectionResponseSchema(bool enablePagination, bool enableCo
ODataContext context = new(model, settings);
// Act & Assert
- var schemas = context.CreateSchemas();
+ context.AddSchemasToDocument(openApiDocument);
- var stringCollectionResponse = schemas["StringCollectionResponse"];
- var flightCollectionResponse = schemas["Microsoft.OData.Service.Sample.TrippinInMemory.Models.FlightCollectionResponse"];
+ var stringCollectionResponse = openApiDocument.Components.Schemas["StringCollectionResponse"];
+ var flightCollectionResponse = openApiDocument.Components.Schemas["Microsoft.OData.Service.Sample.TrippinInMemory.Models.FlightCollectionResponse"];
if (enablePagination || enableCount)
{
Assert.Collection(stringCollectionResponse.AllOf,
item =>
{
- Assert.Equal(referenceId, item.Reference.Id);
+ var itemReference = Assert.IsType(item);
+ Assert.Equal(referenceId, itemReference.Reference.Id);
},
item =>
{
- Assert.Equal("array", item.Properties["value"].Type);
+ Assert.Equal(JsonSchemaType.Array, item.Properties["value"].Type);
});
- Assert.Equal("array", flightCollectionResponse.AllOf?.FirstOrDefault(x => x.Properties.Any())?.Properties["value"].Type);
- Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Flight",
- flightCollectionResponse.AllOf?.FirstOrDefault(x => x.Properties.Any())?.Properties["value"].Items.Reference.Id);
+ Assert.Single(flightCollectionResponse.AllOf?.Where(x => x.Properties.TryGetValue("value", out var valueProp) &&
+ (valueProp.Type & JsonSchemaType.Array) is JsonSchemaType.Array &&
+ valueProp.Items is OpenApiSchemaReference openApiSchemaReference &&
+ "Microsoft.OData.Service.Sample.TrippinInMemory.Models.Flight".Equals(openApiSchemaReference.Reference.Id)));
}
else
{
- Assert.Equal("array", stringCollectionResponse.Properties["value"].Type);
- Assert.Equal("array", flightCollectionResponse.Properties["value"].Type);
- Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Flight", flightCollectionResponse.Properties["value"].Items.Reference.Id);
+ Assert.Equal(JsonSchemaType.Array, stringCollectionResponse.Properties["value"].Type);
+ Assert.Equal(JsonSchemaType.Array, flightCollectionResponse.Properties["value"].Type);
+ var itemsReference = Assert.IsType(flightCollectionResponse.Properties["value"].Items);
+ Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Flight", itemsReference.Reference.Id);
}
}
@@ -87,6 +94,7 @@ public void CreatesRefRequestBodySchema()
{
// Arrange
IEdmModel model = EdmModelHelper.TripServiceModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new()
{
EnableOperationId = true,
@@ -95,15 +103,15 @@ public void CreatesRefRequestBodySchema()
ODataContext context = new(model, settings);
// Act & Assert
- var schemas = context.CreateSchemas();
+ context.AddSchemasToDocument(openApiDocument);
- schemas.TryGetValue(Constants.ReferenceCreateSchemaName, out OpenApiSchema refRequestBody);
+ openApiDocument.Components.Schemas.TryGetValue(Constants.ReferenceCreateSchemaName, out var refRequestBody);
Assert.NotNull(refRequestBody);
- Assert.Equal("object", refRequestBody.Type);
+ Assert.Equal(JsonSchemaType.Object, refRequestBody.Type);
Assert.Equal(Constants.OdataId, refRequestBody.Properties.First().Key);
- Assert.Equal("string", refRequestBody.Properties.First().Value.Type);
- Assert.Equal("object", refRequestBody.AdditionalProperties.Type);
+ Assert.Equal(JsonSchemaType.String, refRequestBody.Properties.First().Value.Type);
+ Assert.Equal(JsonSchemaType.Object, refRequestBody.AdditionalProperties.Type);
}
[Theory]
@@ -113,6 +121,7 @@ public void CreatesRefOdataAnnotationResponseSchemas(bool enableOdataAnnotationR
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
+ OpenApiDocument openApiDocument = new();
OpenApiConvertSettings settings = new()
{
EnableOperationId = true,
@@ -123,13 +132,13 @@ public void CreatesRefOdataAnnotationResponseSchemas(bool enableOdataAnnotationR
ODataContext context = new(model, settings);
// Act
- var schemas = context.CreateSchemas();
+ context.AddSchemasToDocument(openApiDocument);
// Assert
- Assert.NotNull(schemas);
- Assert.NotEmpty(schemas);
- schemas.TryGetValue(Constants.BaseCollectionPaginationCountResponse, out OpenApiSchema refPaginationCount);
- schemas.TryGetValue(Constants.BaseDeltaFunctionResponse, out OpenApiSchema refDeltaFunc);
+ Assert.NotNull(openApiDocument.Components.Schemas);
+ Assert.NotEmpty(openApiDocument.Components.Schemas);
+ openApiDocument.Components.Schemas.TryGetValue(Constants.BaseCollectionPaginationCountResponse, out var refPaginationCount);
+ openApiDocument.Components.Schemas.TryGetValue(Constants.BaseDeltaFunctionResponse, out var refDeltaFunc);
if (enableOdataAnnotationRef)
{
Assert.NotNull(refPaginationCount);
@@ -168,7 +177,7 @@ public void CreateStructuredTypeSchemaThrowArgumentNullEnumType()
}
[Fact]
- public void CreateStructuredTypeSchemaForEntityTypeWithDiscriminatorValueEnabledReturnsCorrectSchema()
+ public async Task CreateStructuredTypeSchemaForEntityTypeWithDiscriminatorValueEnabledReturnsCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -186,12 +195,12 @@ public void CreateStructuredTypeSchemaForEntityTypeWithDiscriminatorValueEnabled
// Act
var schema = context.CreateStructuredTypeSchema(entity);
var derivedSchema = context.CreateStructuredTypeSchema(derivedEntity);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0));
// Assert
Assert.True(derivedSchema.AllOf.FirstOrDefault(x => derivedType.Equals(x.Title))?.Properties.ContainsKey("@odata.type"));
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""allOf"": [
{
""$ref"": ""#/components/schemas/microsoft.graph.entity""
@@ -254,13 +263,13 @@ public void CreateStructuredTypeSchemaForEntityTypeWithDiscriminatorValueEnabled
}
}
]
-}".ChangeLineBreaks(), json);
+}"), json));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateStructuredTypeSchemaForComplexTypeWithDiscriminatorValueEnabledReturnsCorrectSchema(bool enableTypeDisambiguationForOdataTypePropertyDefaultValue)
+ public async Task CreateStructuredTypeSchemaForComplexTypeWithDiscriminatorValueEnabledReturnsCorrectSchema(bool enableTypeDisambiguationForOdataTypePropertyDefaultValue)
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -275,7 +284,7 @@ public void CreateStructuredTypeSchemaForComplexTypeWithDiscriminatorValueEnable
// Act
var schema = context.CreateStructuredTypeSchema(complex);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
@@ -307,7 +316,7 @@ public void CreateStructuredTypeSchemaForComplexTypeWithDiscriminatorValueEnable
""#microsoft.graph.singleUser"": ""#/components/schemas/microsoft.graph.singleUser""
}
}
-}".ChangeLineBreaks()
+}"
:
@"{
""title"": ""userSet"",
@@ -337,13 +346,13 @@ public void CreateStructuredTypeSchemaForComplexTypeWithDiscriminatorValueEnable
""#microsoft.graph.singleUser"": ""#/components/schemas/microsoft.graph.singleUser""
}
}
-}".ChangeLineBreaks();
+}";
- Assert.Equal(expected, json);
+ Assert.True(JsonObject.DeepEquals(JsonObject.Parse(expected), JsonObject.Parse(json)));
}
[Fact]
- public void CreateStructuredTypePropertiesSchemaWithCustomAttributeReturnsCorrectSchema()
+ public async Task CreateStructuredTypePropertiesSchemaWithCustomAttributeReturnsCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -354,11 +363,11 @@ public void CreateStructuredTypePropertiesSchemaWithCustomAttributeReturnsCorrec
// Act
OpenApiSchema schema = context.CreateStructuredTypeSchema(entity);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonObject.DeepEquals(JsonObject.Parse(@"{
""allOf"": [
{
""$ref"": ""#/components/schemas/microsoft.graph.entity""
@@ -430,11 +439,11 @@ public void CreateStructuredTypePropertiesSchemaWithCustomAttributeReturnsCorrec
}
}
]
-}".ChangeLineBreaks(), json);
+}"), JsonObject.Parse(json)));
}
[Fact]
- public void CreateComplexTypeWithoutBaseSchemaReturnCorrectSchema()
+ public async Task CreateComplexTypeWithoutBaseSchemaReturnCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.MultipleInheritanceEdmModel;
@@ -450,7 +459,7 @@ public void CreateComplexTypeWithoutBaseSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.Null(schema.AllOf);
Assert.NotNull(schema.Properties);
@@ -460,11 +469,11 @@ public void CreateComplexTypeWithoutBaseSchemaReturnCorrectSchema()
Assert.Equal("Address", schema.Title);
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonObject.DeepEquals(JsonObject.Parse(@"{
""title"": ""Address"",
""type"": ""object"",
""properties"": {
@@ -482,11 +491,11 @@ public void CreateComplexTypeWithoutBaseSchemaReturnCorrectSchema()
""Street"": ""string"",
""City"": ""string""
}
-}".ChangeLineBreaks(), json);
+}"), JsonObject.Parse(json)));
}
[Fact]
- public void CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
+ public async Task CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.MultipleInheritanceEdmModel;
@@ -503,7 +512,7 @@ public void CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.True(String.IsNullOrEmpty(schema.Type));
+ Assert.True(String.IsNullOrEmpty(schema.Type.ToIdentifier()));
Assert.NotNull(schema.AllOf);
Assert.Null(schema.AnyOf);
@@ -511,13 +520,13 @@ public void CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
Assert.Null(schema.Properties);
Assert.Equal(2, schema.AllOf.Count);
- var baseSchema = schema.AllOf.First();
+ var baseSchema = Assert.IsType(schema.AllOf.First());
Assert.NotNull(baseSchema.Reference);
Assert.Equal(ReferenceType.Schema, baseSchema.Reference.Type);
Assert.Equal("NS.LandPlant", baseSchema.Reference.Id);
var declaredSchema = schema.AllOf.Last();
- Assert.Equal("object", declaredSchema.Type);
+ Assert.Equal(JsonSchemaType.Object, declaredSchema.Type);
Assert.Null(declaredSchema.AllOf);
Assert.Null(declaredSchema.AnyOf);
Assert.Null(declaredSchema.OneOf);
@@ -528,17 +537,17 @@ public void CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
Assert.Equal("Price", property.Key);
Assert.Equal("decimal", property.Value.OneOf.FirstOrDefault(x => !string.IsNullOrEmpty(x.Format))?.Format);
Assert.NotNull(property.Value.OneOf);
- Assert.Equal(new string[] { "number", "string" }, property.Value.OneOf.Select(e => e.Type));
+ Assert.Equal([JsonSchemaType.Number | JsonSchemaType.Null, JsonSchemaType.String | JsonSchemaType.Null], property.Value.OneOf.Select(e => e.Type));
Assert.Equal("Complex type 'Tree' description.", declaredSchema.Description);
Assert.Equal("Tree", declaredSchema.Title);
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""allOf"": [
{
""$ref"": ""#/components/schemas/NS.LandPlant""
@@ -572,14 +581,13 @@ public void CreateComplexTypeWithBaseSchemaReturnCorrectSchema()
""@odata.type"": ""NS.Continent""
},
""Name"": ""string"",
- ""Price"": ""decimal""
+ ""Price"": 0
}
-}"
-.ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void CreateEntityTypeWithoutBaseSchemaReturnCorrectSchema()
+ public async Task CreateEntityTypeWithoutBaseSchemaReturnCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.MultipleInheritanceEdmModel;
@@ -595,7 +603,7 @@ public void CreateEntityTypeWithoutBaseSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.Null(schema.AllOf);
Assert.NotNull(schema.Properties);
@@ -605,11 +613,11 @@ public void CreateEntityTypeWithoutBaseSchemaReturnCorrectSchema()
Assert.Equal("Zoo", schema.Title);
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""title"": ""Zoo"",
""type"": ""object"",
""properties"": {
@@ -629,18 +637,18 @@ public void CreateEntityTypeWithoutBaseSchemaReturnCorrectSchema()
},
""description"": ""Entity type 'Zoo' description."",
""example"": {
- ""Id"": ""number (identifier)"",
+ ""Id"": 0,
""Creatures"": [
{
""@odata.type"": ""NS.Creature""
}
]
}
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
+ public async Task CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.MultipleInheritanceEdmModel;
@@ -656,7 +664,7 @@ public void CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.True(String.IsNullOrEmpty(schema.Type));
+ Assert.True(String.IsNullOrEmpty(schema.Type.ToIdentifier()));
Assert.NotNull(schema.AllOf);
Assert.Null(schema.AnyOf);
@@ -664,13 +672,13 @@ public void CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
Assert.Null(schema.Properties);
Assert.Equal(2, schema.AllOf.Count);
- var baseSchema = schema.AllOf.First();
+ var baseSchema = Assert.IsType(schema.AllOf.First());
Assert.NotNull(baseSchema.Reference);
Assert.Equal(ReferenceType.Schema, baseSchema.Reference.Type);
Assert.Equal("NS.Animal", baseSchema.Reference.Id);
var declaredSchema = schema.AllOf.Last();
- Assert.Equal("object", declaredSchema.Type);
+ Assert.Equal(JsonSchemaType.Object, declaredSchema.Type);
Assert.Null(declaredSchema.AllOf);
Assert.Null(declaredSchema.AnyOf);
Assert.Null(declaredSchema.OneOf);
@@ -679,18 +687,18 @@ public void CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
Assert.Single(declaredSchema.Properties);
var property = Assert.Single(declaredSchema.Properties);
Assert.Equal("Name", property.Key);
- Assert.Equal("string", property.Value.Type);
+ Assert.Equal(JsonSchemaType.String, property.Value.Type);
Assert.Null(property.Value.OneOf);
Assert.Equal("Entity type 'Human' description.", declaredSchema.Description);
Assert.Equal("Human", declaredSchema.Title);
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
_output.WriteLine(json);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""allOf"": [
{
""$ref"": ""#/components/schemas/NS.Animal""
@@ -707,12 +715,11 @@ public void CreateEntityTypeWithBaseSchemaReturnCorrectSchema()
}
],
""example"": {
- ""Id"": ""number (identifier)"",
- ""Age"": ""number"",
+ ""Id"": 0,
+ ""Age"": 0,
""Name"": ""string""
}
-}"
-.ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
@@ -732,7 +739,7 @@ public void CreateEntityTypeWithCrossReferenceBaseSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.True(String.IsNullOrEmpty(schema.Type));
+ Assert.True(string.IsNullOrEmpty(schema.Type.ToIdentifier()));
Assert.NotNull(schema.AllOf);
Assert.Null(schema.AnyOf);
@@ -740,13 +747,13 @@ public void CreateEntityTypeWithCrossReferenceBaseSchemaReturnCorrectSchema()
Assert.Null(schema.Properties);
Assert.Equal(2, schema.AllOf.Count);
- var baseSchema = schema.AllOf.First();
+ var baseSchema = Assert.IsType(schema.AllOf.First());
Assert.NotNull(baseSchema.Reference);
Assert.Equal(ReferenceType.Schema, baseSchema.Reference.Type);
Assert.Equal("SubNS.CustomerBase", baseSchema.Reference.Id);
var declaredSchema = schema.AllOf.Last();
- Assert.Equal("object", declaredSchema.Type);
+ Assert.Equal(JsonSchemaType.Object, declaredSchema.Type);
Assert.Null(declaredSchema.AllOf);
Assert.Null(declaredSchema.AnyOf);
Assert.Null(declaredSchema.OneOf);
@@ -755,7 +762,7 @@ public void CreateEntityTypeWithCrossReferenceBaseSchemaReturnCorrectSchema()
Assert.Single(declaredSchema.Properties);
var property = Assert.Single(declaredSchema.Properties);
Assert.Equal("Extra", property.Key);
- Assert.Equal("number", property.Value.Type);
+ Assert.Equal(JsonSchemaType.Number, property.Value.Type);
Assert.Null(property.Value.OneOf);
Assert.Equal("Customer", declaredSchema.Title);
@@ -764,7 +771,7 @@ public void CreateEntityTypeWithCrossReferenceBaseSchemaReturnCorrectSchema()
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateStructuredTypeSchemaForEntityTypeWithDefaultValueForOdataTypePropertyEnabledOrDisabledReturnsCorrectSchema(bool enableTypeDisambiguationForOdataTypePropertyDefaultValue)
+ public async Task CreateStructuredTypeSchemaForEntityTypeWithDefaultValueForOdataTypePropertyEnabledOrDisabledReturnsCorrectSchema(bool enableTypeDisambiguationForOdataTypePropertyDefaultValue)
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -779,7 +786,7 @@ public void CreateStructuredTypeSchemaForEntityTypeWithDefaultValueForOdataTypeP
// Act
var schema = context.CreateStructuredTypeSchema(entityType);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
@@ -810,7 +817,7 @@ public void CreateEnumTypeSchemaThrowArgumentNullEnumType()
}
[Fact]
- public void CreateEnumTypeSchemaReturnCorrectSchema()
+ public async Task CreateEnumTypeSchemaReturnCorrectSchema()
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
@@ -823,20 +830,20 @@ public void CreateEnumTypeSchemaReturnCorrectSchema()
// Assert
Assert.NotNull(schema);
- Assert.Equal("string", schema.Type);
+ Assert.Equal(JsonSchemaType.String, schema.Type);
Assert.Equal("Enum type 'Color' description.", schema.Description);
Assert.Equal("Color", schema.Title);
Assert.NotNull(schema.Enum);
Assert.Equal(2, schema.Enum.Count);
- Assert.Equal(new string[] { "Blue", "White" }, schema.Enum.Select(e => ((OpenApiString)e).Value));
+ Assert.Equal([ "Blue", "White" ], schema.Enum.Select(e => e.ToString()));
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.NotNull(json);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""title"": ""Color"",
""enum"": [
""Blue"",
@@ -844,7 +851,7 @@ public void CreateEnumTypeSchemaReturnCorrectSchema()
],
""type"": ""string"",
""description"": ""Enum type 'Color' description.""
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
#endregion
@@ -852,7 +859,7 @@ public void CreateEnumTypeSchemaReturnCorrectSchema()
[Theory]
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
- public void CreatePropertySchemaForNonNullableEnumPropertyReturnSchema(OpenApiSpecVersion specVersion)
+ public async Task CreatePropertySchemaForNonNullableEnumPropertyReturnSchema(OpenApiSpecVersion specVersion)
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
@@ -867,28 +874,29 @@ public void CreatePropertySchemaForNonNullableEnumPropertyReturnSchema(OpenApiSp
// Act
var schema = context.CreatePropertySchema(property);
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(specVersion);
+ string json = await schema.SerializeAsJsonAsync(specVersion);
// Assert
if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""$ref"": ""#/definitions/DefaultNs.Color""
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""$ref"": ""#/components/schemas/DefaultNs.Color""
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
}
[Theory]
+ [InlineData(OpenApiSpecVersion.OpenApi3_1)]
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
- public void CreatePropertySchemaForNullableEnumPropertyReturnSchema(OpenApiSpecVersion specVersion)
+ public async Task CreatePropertySchemaForNullableEnumPropertyReturnSchema(OpenApiSpecVersion specVersion)
{
// Arrange
IEdmModel model = EdmModelHelper.BasicEdmModel;
@@ -897,43 +905,61 @@ public void CreatePropertySchemaForNullableEnumPropertyReturnSchema(OpenApiSpecV
context.Settings.OpenApiSpecVersion = specVersion;
IEdmEnumType enumType = model.SchemaElements.OfType().First(e => e.Name == "Color");
- EdmEntityType entitType = new EdmEntityType("NS", "Entity");
- IEdmProperty property = new EdmStructuralProperty(entitType, "ColorEnumValue", new EdmEnumTypeReference(enumType, true), "yellow");
+ EdmEntityType entityType = new EdmEntityType("NS", "Entity");
+ IEdmProperty property = new EdmStructuralProperty(entityType, "ColorEnumValue", new EdmEnumTypeReference(enumType, true), "yellow");
// Act
var schema = context.CreatePropertySchema(property);
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(specVersion);
+ string json = await schema.SerializeAsJsonAsync(specVersion);
_output.WriteLine(json);
- // Assert
- if (specVersion == OpenApiSpecVersion.OpenApi2_0)
- {
- Assert.Equal(@"{
- ""$ref"": ""#/definitions/DefaultNs.Color""
-}".ChangeLineBreaks(), json);
- }
- else
- {
- Assert.Equal(@"{
- ""anyOf"": [
- {
- ""$ref"": ""#/components/schemas/DefaultNs.Color""
- },
- {
- ""type"": ""object"",
- ""nullable"": true
- }
- ],
- ""default"": ""yellow""
-}".ChangeLineBreaks(), json);
- }
+ var expected = JsonNode.Parse(specVersion switch {
+ OpenApiSpecVersion.OpenApi2_0 =>
+ """
+ {
+ "$ref": "#/definitions/DefaultNs.Color"
+ }
+ """,
+ OpenApiSpecVersion.OpenApi3_0 =>
+ """
+ {
+ "anyOf": [
+ {
+ "$ref": "#/components/schemas/DefaultNs.Color"
+ },
+ {
+ "type": "object",
+ "nullable": true
+ }
+ ],
+ "default": "yellow"
+ }
+ """,
+ OpenApiSpecVersion.OpenApi3_1 =>
+ """
+ {
+ "anyOf": [
+ {
+ "$ref": "#/components/schemas/DefaultNs.Color"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": "yellow"
+ }
+ """,
+ _ => throw new NotSupportedException()
+ });
+
+ Assert.True(JsonNode.DeepEquals(expected, JsonNode.Parse(json)));
}
[Theory]
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
- public void CreatePropertySchemaWithComputedAnnotationReturnsCorrectSchema(OpenApiSpecVersion specVersion)
+ public async Task CreatePropertySchemaWithComputedAnnotationReturnsCorrectSchema(OpenApiSpecVersion specVersion)
{
// Arrange
IEdmModel model = EdmModelHelper.GraphBetaModel;
@@ -947,28 +973,28 @@ public void CreatePropertySchemaWithComputedAnnotationReturnsCorrectSchema(OpenA
// Act
var schema = context.CreatePropertySchema(property);
Assert.NotNull(schema);
- string json = schema.SerializeAsJson(specVersion);
+ var json = JsonNode.Parse(await schema.SerializeAsJsonAsync(specVersion));
// Assert
if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""format"": ""duration"",
""description"": ""The length of the appointment, denoted in ISO8601 format."",
""pattern"": ""^-?P([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+([.][0-9]+)?S)?)?$"",
""type"": ""string"",
""readOnly"": true
-}".ChangeLineBreaks(), json);
+}"), json));
}
else
{
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""pattern"": ""^-?P([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+([.][0-9]+)?S)?)?$"",
""type"": ""string"",
""description"": ""The length of the appointment, denoted in ISO8601 format."",
""format"": ""duration"",
""readOnly"": true
-}".ChangeLineBreaks(), json);
+}"), json));
}
}
#endregion
@@ -1010,7 +1036,7 @@ public void GetDerivedTypesReferenceSchemaReturnsNullSchemaIfNotExist()
#endregion
[Fact]
- public void NonNullableBooleanPropertyWithDefaultValueWorks()
+ public async Task NonNullableBooleanPropertyWithDefaultValueWorks()
{
// Arrange
ODataContext context = new ODataContext(EdmModelHelper.BasicEdmModel);
@@ -1023,17 +1049,17 @@ public void NonNullableBooleanPropertyWithDefaultValueWorks()
// Assert
Assert.NotNull(schema);
- Assert.Equal("boolean", schema.Type);
+ Assert.Equal(JsonSchemaType.Boolean, schema.Type);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""type"": ""boolean"",
""default"": false
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void NonNullableBinaryPropertyWithBothMaxLengthAndDefaultValueWorks()
+ public async Task NonNullableBinaryPropertyWithBothMaxLengthAndDefaultValueWorks()
{
// Arrange
ODataContext context = new ODataContext(EdmModelHelper.BasicEdmModel);
@@ -1048,19 +1074,19 @@ public void NonNullableBinaryPropertyWithBothMaxLengthAndDefaultValueWorks()
// Assert
Assert.NotNull(schema);
- Assert.Equal("string", schema.Type);
+ Assert.Equal(JsonSchemaType.String, schema.Type);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""maxLength"": 44,
""type"": ""string"",
""format"": ""base64url"",
""default"": ""T0RhdGE""
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void NonNullableIntegerPropertyWithDefaultValueWorks()
+ public async Task NonNullableIntegerPropertyWithDefaultValueWorks()
{
// Arrange
ODataContext context = new ODataContext(EdmModelHelper.BasicEdmModel);
@@ -1073,20 +1099,20 @@ public void NonNullableIntegerPropertyWithDefaultValueWorks()
// Assert
Assert.NotNull(schema);
- Assert.Equal("number", schema.Type);
+ Assert.Equal(JsonSchemaType.Number, schema.Type);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""maximum"": 2147483647,
""minimum"": -2147483648,
""type"": ""number"",
""format"": ""int32"",
""default"": -128
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void NonNullableDoublePropertyWithDefaultStringWorks()
+ public async Task NonNullableDoublePropertyWithDefaultStringWorks()
{
// Arrange
ODataContext context = new ODataContext(EdmModelHelper.BasicEdmModel);
@@ -1101,9 +1127,9 @@ public void NonNullableDoublePropertyWithDefaultStringWorks()
Assert.NotNull(schema);
Assert.Null(schema.Type);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(@"{
""oneOf"": [
{
""type"": ""number"",
@@ -1119,12 +1145,12 @@ public void NonNullableDoublePropertyWithDefaultStringWorks()
}
],
""default"": ""3.1415926535897931""
-}".ChangeLineBreaks(), json);
+}"), JsonNode.Parse(json)));
}
[Fact]
- public void NonNullableUntypedPropertyWorks()
+ public async Task NonNullableUntypedPropertyWorks()
{
ODataContext context = new ODataContext(
EdmModelHelper.BasicEdmModel,
@@ -1132,9 +1158,9 @@ public void NonNullableUntypedPropertyWorks()
{
ShowSchemaExamples = true
});
- EdmEntityType entitType = new EdmEntityType("NS", "Entity");
+ EdmEntityType entityType = new EdmEntityType("NS", "Entity");
IEdmStructuralProperty property = new EdmStructuralProperty(
- entitType, "UntypedProperty", EdmCoreModel.Instance.GetUntyped());
+ entityType, "UntypedProperty", EdmCoreModel.Instance.GetUntyped());
// Act
var schema = context.CreatePropertySchema(property);
@@ -1143,7 +1169,7 @@ public void NonNullableUntypedPropertyWorks()
Assert.NotNull(schema);
Assert.Null(schema.Type);
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Equal("{ }", json);
}
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSecuritySchemeGeneratorTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSecuritySchemeGeneratorTests.cs
index 2e7813fc8..6686ea29a 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSecuritySchemeGeneratorTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSecuritySchemeGeneratorTests.cs
@@ -14,19 +14,23 @@
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
using Xunit;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
namespace Microsoft.OpenApi.OData.Tests
{
public class OpenApiSecuritySchemeGeneratorTest
{
[Fact]
- public void CreateSecuritySchemesWorksForAuthorizationsOnEntitySetContainer()
+ public async Task CreateSecuritySchemesWorksForAuthorizationsOnEntitySetContainer()
{
// Arrange
ODataContext context = new ODataContext(GetEdmModel());
+ OpenApiDocument openApiDocument = new();
// Act
- var schemes = context.CreateSecuritySchemes();
+ context.AddSecuritySchemesToDocument(openApiDocument);
+ var schemes = openApiDocument.Components.SecuritySchemes;
// Assert
Assert.NotNull(schemes);
@@ -39,8 +43,8 @@ public void CreateSecuritySchemesWorksForAuthorizationsOnEntitySetContainer()
Assert.Equal("http://TokenUrl", scheme.Flows.ClientCredentials.TokenUrl.OriginalString);
Assert.Equal("http://RefreshUrl", scheme.Flows.ClientCredentials.RefreshUrl.OriginalString);
Assert.Equal("OAuth2ClientCredentials Description", scheme.Description);
- string json = scheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ string json = await scheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ var expectedJson = JsonNode.Parse(@"{
""type"": ""oauth2"",
""description"": ""OAuth2ClientCredentials Description"",
""flows"": {
@@ -52,17 +56,19 @@ public void CreateSecuritySchemesWorksForAuthorizationsOnEntitySetContainer()
}
}
}
-}".ChangeLineBreaks(), json);
+}");
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(json), expectedJson));
scheme = schemes["Http Name"];
Assert.Equal(SecuritySchemeType.Http, scheme.Type);
- json = scheme.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
- Assert.Equal(@"{
+ json = await scheme.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
+ expectedJson = JsonNode.Parse(@"{
""type"": ""http"",
""description"": ""Http Description"",
""scheme"": ""Http Scheme"",
""bearerFormat"": ""Http BearerFormat""
-}".ChangeLineBreaks(), json);
+}");
+ Assert.True(JsonNode.DeepEquals(JsonNode.Parse(json), expectedJson));
}
private static IEdmModel GetEdmModel()
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSpatialTypeSchemaGeneratorTest.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSpatialTypeSchemaGeneratorTest.cs
index a036b1ca6..70772d6db 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSpatialTypeSchemaGeneratorTest.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Generator/OpenApiSpatialTypeSchemaGeneratorTest.cs
@@ -5,6 +5,7 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.OData.Edm;
@@ -22,7 +23,7 @@ public void CreateSpatialSchemasThrowArgumentNullContext()
ODataContext context = null;
// Act & Assert
- Assert.Throws("context", () => context.CreateSpatialSchemas());
+ Assert.Throws("context", context.CreateSpatialSchemas);
}
[Fact]
@@ -82,14 +83,14 @@ public void CreateSpatialSchemasReturnFullSpatialSchemasForModelWithEdmSpatialTy
}
[Fact]
- public void CreateEdmGeographySchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographySchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographySchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -98,14 +99,14 @@ public void CreateEdmGeographySchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyPointSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyPointSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyPointSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -114,14 +115,14 @@ public void CreateEdmGeographyPointSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyLineStringSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyLineStringSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyLineStringSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -130,14 +131,14 @@ public void CreateEdmGeographyLineStringSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyPolygonSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyPolygonSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyPolygonSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -146,14 +147,14 @@ public void CreateEdmGeographyPolygonSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyMultiPointSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyMultiPointSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyMultiPointSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -162,14 +163,14 @@ public void CreateEdmGeographyMultiPointSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyMultiLineStringSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyMultiLineStringSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyMultiLineStringSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -178,14 +179,14 @@ public void CreateEdmGeographyMultiLineStringSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyMultiPolygonSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyMultiPolygonSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyMultiPolygonSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -194,14 +195,14 @@ public void CreateEdmGeographyMultiPolygonSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeographyCollectionSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeographyCollectionSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeographyCollectionSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -210,14 +211,14 @@ public void CreateEdmGeographyCollectionSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometrySchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometrySchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometrySchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -249,14 +250,14 @@ public void CreateEdmGeometrySchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometryPointSchemaSerializeAsYamlWorks() // test yaml
+ public async Task CreateEdmGeometryPointSchemaSerializeAsYamlWorks() // test yaml
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryPointSchema();
Assert.NotNull(schema); // guard
// Act
- string yaml = schema.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0);
+ string yaml = await schema.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(
@@ -275,14 +276,14 @@ public void CreateEdmGeometryPointSchemaSerializeAsYamlWorks() // test yaml
}
[Fact]
- public void CreateEdmGeometryLineStringSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometryLineStringSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryLineStringSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -309,14 +310,14 @@ public void CreateEdmGeometryLineStringSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometryPolygonSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometryPolygonSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryPolygonSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -346,14 +347,14 @@ public void CreateEdmGeometryPolygonSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometryMultiPointSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometryMultiPointSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryMultiPointSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -379,14 +380,14 @@ public void CreateEdmGeometryMultiPointSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometryMultiLineStringSchemaSerializeAsYamlWorks() // Test yaml
+ public async Task CreateEdmGeometryMultiLineStringSchemaSerializeAsYamlWorks() // Test yaml
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryMultiLineStringSchema();
Assert.NotNull(schema); // guard
// Act
- string yaml = schema.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0);
+ string yaml = await schema.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"required:
@@ -407,14 +408,14 @@ public void CreateEdmGeometryMultiLineStringSchemaSerializeAsYamlWorks() // Test
}
[Fact]
- public void CreateEdmGeometryMultiPolygonSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometryMultiPolygonSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryMultiPolygonSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -447,14 +448,14 @@ public void CreateEdmGeometryMultiPolygonSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateEdmGeometryCollectionSchemaSerializeAsJsonWorks()
+ public async Task CreateEdmGeometryCollectionSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateEdmGeometryCollectionSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
@@ -480,14 +481,14 @@ public void CreateEdmGeometryCollectionSchemaSerializeAsJsonWorks()
}
[Fact]
- public void CreateGeoJSON_PositionSchemaSerializeAsJsonWorks()
+ public async Task CreateGeoJSON_PositionSchemaSerializeAsJsonWorks()
{
// Arrange
var schema = OpenApiSpatialTypeSchemaGenerator.CreateGeoJsonPointSchema();
Assert.NotNull(schema); // guard
// Act
- string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await schema.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
// Assert
Assert.Equal(@"{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj b/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj
index af5b65e22..c9fb7ef59 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj
@@ -15,23 +15,31 @@
+
+
+
+
+
+
+
+
@@ -42,22 +50,30 @@
+
+
+
+
+
+
+
+
@@ -73,7 +89,8 @@
all
-
+
+
all
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs
index bde8ab378..84f7e9fa2 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/ComplexPropertyPutOperationHandlerTests.cs
@@ -5,6 +5,7 @@
using System.Linq;
using Microsoft.OData.Edm;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Xunit;
@@ -102,9 +103,9 @@ public void CreateComplexPropertyPutOperationReturnsCorrectOperationForCollectio
var schema = put.RequestBody?.Content.FirstOrDefault().Value?.Schema;
Assert.NotNull(schema);
- Assert.Equal("object", schema.Type);
+ Assert.Equal(JsonSchemaType.Object, schema.Type);
Assert.Equal("value", schema.Properties.FirstOrDefault().Key);
- Assert.Equal("array", schema.Properties.FirstOrDefault().Value.Type);
+ Assert.Equal(JsonSchemaType.Array, schema.Properties.FirstOrDefault().Value.Type);
if (enableOperationId)
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/DollarCountGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/DollarCountGetOperationHandlerTests.cs
index f2ca5ddf9..b7ba20554 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/DollarCountGetOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/DollarCountGetOperationHandlerTests.cs
@@ -14,7 +14,14 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class DollarCountGetOperationHandlerTests
{
- private readonly DollarCountGetOperationHandler _operationHandler = new();
+ private readonly OpenApiDocument openApiDocument = new();
+ private static DollarCountGetOperationHandler _operationHandler => new();
+ public DollarCountGetOperationHandlerTests()
+ {
+ openApiDocument.AddComponent("search", new OpenApiParameter {Name = "search", In = ParameterLocation.Query, Schema = new OpenApiSchema {Type = JsonSchemaType.String}});
+ openApiDocument.AddComponent("filter", new OpenApiParameter {Name = "filter", In = ParameterLocation.Query, Schema = new OpenApiSchema {Type = JsonSchemaType.String}});
+ openApiDocument.AddComponent("ConsistencyLevel", new OpenApiParameter {Name = "ConsistencyLevel", In = ParameterLocation.Query, Schema = new OpenApiSchema {Type = JsonSchemaType.String}});
+ }
[Theory]
[InlineData(true, true)]
@@ -50,8 +57,8 @@ public void CreateDollarCountGetOperationForNavigationPropertyReturnsCorrectOper
Assert.NotNull(operation.Parameters);
Assert.Equal(4, operation.Parameters.Count);
- Assert.Equal(new[] { "UserName", "ConsistencyLevel", "search", "filter"},
- operation.Parameters.Select(x => x.Name ?? x.Reference.Id).ToList());
+ Assert.Equivalent(new[] { "UserName", "ConsistencyLevel", "search", "filter"},
+ operation.Parameters.Select(x => x.Name).ToList());
Assert.Null(operation.RequestBody);
@@ -91,8 +98,8 @@ public void CreateDollarCountGetOperationForNavigationPropertyWithTargetPathAnno
// Assert
Assert.NotNull(operation.Parameters);
Assert.Equal(4, operation.Parameters.Count);
- Assert.Equal(new[] { "id", "ConsistencyLevel", "search", "filter" },
- operation.Parameters.Select(x => x.Name ?? x.Reference.Id).ToList());
+ Assert.Equivalent(new[] { "id", "ConsistencyLevel", "search", "filter" },
+ operation.Parameters.Select(x => x.Name).ToList());
Assert.Equal("Get the number of the resource", operation.Summary);
@@ -130,8 +137,8 @@ public void CreateDollarCountGetOperationForNavigationSourceReturnsCorrectOperat
Assert.Equal("Get the number of the resource", operation.Summary);
Assert.NotNull(operation.Parameters);
Assert.Equal(3, operation.Parameters.Count);
- Assert.Equal(new[] { "ConsistencyLevel", "search", "filter" },
- operation.Parameters.Select(x => x.Name ?? x.Reference.Id).ToList());
+ Assert.Equivalent(new[] { "ConsistencyLevel", "search", "filter" },
+ operation.Parameters.Select(x => x.Name).ToList());
Assert.Null(operation.RequestBody);
Assert.Equal(2, operation.Responses.Count);
@@ -168,8 +175,8 @@ public void CreateDollarCountGetOperationForNavigationSourceWithTargetPathAnnota
Assert.Equal("Get the number of the resource", operation.Summary);
Assert.NotNull(operation.Parameters);
Assert.Equal(3, operation.Parameters.Count);
- Assert.Equal(new[] { "ConsistencyLevel", "search", "filter" },
- operation.Parameters.Select(x => x.Name ?? x.Reference.Id).ToList());
+ Assert.Equivalent(new[] { "ConsistencyLevel", "search", "filter" },
+ operation.Parameters.Select(x => x.Name).ToList());
Assert.Null(operation.RequestBody);
Assert.Equal(2, operation.Responses.Count);
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionImportOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionImportOperationHandlerTests.cs
index acb5f3a72..9fa4495e5 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionImportOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionImportOperationHandlerTests.cs
@@ -4,10 +4,12 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -16,7 +18,17 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EdmActionImportOperationHandlerTests
{
- private EdmActionImportOperationHandler _operationHandler = new EdmActionImportOperationHandler();
+ private readonly OpenApiDocument openApiDocument = new();
+ private static EdmActionImportOperationHandler _operationHandler => new();
+ public EdmActionImportOperationHandlerTests()
+ {
+ openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
[Fact]
public void CreateOperationForEdmActionImportReturnsCorrectOperation()
@@ -92,7 +104,7 @@ public void CreateOperationForEdmActionImportReturnsCorrectOperationId(bool enab
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void OperationRestrictionsTermWorksToCreateOperationForEdmActionImport(bool enableAnnotation)
+ public async Task OperationRestrictionsTermWorksToCreateOperationForEdmActionImport(bool enableAnnotation)
{
string template = @"
@@ -191,7 +203,7 @@ public void OperationRestrictionsTermWorksToCreateOperationForEdmActionImport(bo
{
Assert.Equal(2, operation.Security.Count);
- string json = operation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs
index 42557659b..b16a58f9f 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs
@@ -4,11 +4,16 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Reflection.Metadata;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -16,7 +21,17 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EdmActionOperationHandlerTests
{
- private EdmActionOperationHandler _operationHandler = new EdmActionOperationHandler();
+ public EdmActionOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+ private static EdmActionOperationHandler _operationHandler => new();
[Fact]
public void CreateOperationForEdmActionReturnsCorrectOperation()
@@ -33,6 +48,7 @@ public void CreateOperationForEdmActionReturnsCorrectOperation()
// Act
var operation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(operation);
@@ -46,11 +62,8 @@ public void CreateOperationForEdmActionReturnsCorrectOperation()
Assert.Single(operation.Parameters);
Assert.Equal(new string[] { "UserName" }, operation.Parameters.Select(p => p.Name));
- Assert.NotNull(operation.RequestBody);
- if (operation.RequestBody.Reference != null)
- Assert.Equal("ShareTripRequestBody", operation.RequestBody.Reference.Id);
- else
- Assert.Equal("Action parameters", operation.RequestBody.Description);
+ var requestBodyReference = Assert.IsType(operation.RequestBody);
+ Assert.Equal("ShareTripRequestBody", requestBodyReference.Reference.Id);
Assert.Equal(2, operation.Responses.Count);
Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key));
@@ -73,6 +86,7 @@ public void CreateOperationForEdmActionReturnsCorrectOperationHierarchicalClass(
// Act
var operation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(operation);
@@ -192,7 +206,7 @@ public void CreateOperationForEdmActionWithTypeCastReturnsCorrectOperationId(boo
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void OperationRestrictionsTermWorksToCreateOperationForEdmAction(bool enableAnnotation)
+ public async Task OperationRestrictionsTermWorksToCreateOperationForEdmAction(bool enableAnnotation)
{
string template = @"
@@ -276,7 +290,7 @@ public void OperationRestrictionsTermWorksToCreateOperationForEdmAction(bool ena
{
Assert.Equal(2, operation.Security.Count);
- string json = operation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
@@ -372,8 +386,8 @@ public void CreateOperationForEdmActionWithCollectionReturnTypeHasResponseWithNe
// Assert
if (enablePagination && enableOdataAnnotationRef)
{
- var reference = operation.Responses.First().Value.Content.First().Value.Schema.AllOf.First().Reference.Id;
- Assert.Equal(Common.Constants.BaseCollectionPaginationCountResponse, reference);
+ var schemaReference = Assert.IsType(operation.Responses.First().Value.Content.First().Value.Schema.AllOf[0]);
+ Assert.Equal(Common.Constants.BaseCollectionPaginationCountResponse, schemaReference.Reference.Id);
}
else if (enablePagination)
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs
index 8869dd6df..f63fd4eef 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionImportOperationHandlerTests.cs
@@ -4,11 +4,14 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -16,7 +19,17 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EdmFunctionImportOperationHandlerTests
{
- private EdmFunctionImportOperationHandler _operationHandler = new EdmFunctionImportOperationHandler();
+ public EdmFunctionImportOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+ private static EdmFunctionImportOperationHandler _operationHandler => new();
[Theory]
[InlineData(true)]
@@ -36,6 +49,7 @@ public void CreateOperationForEdmFunctionImportReturnsCorrectOperation(bool useH
// Act
var operation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(operation);
@@ -153,7 +167,7 @@ public void CreateOperationIdWithSHA5ForOverloadEdmFunctionImport(bool enableOpe
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void OperationRestrictionsTermWorksToCreateOperationForEdmFunctionImport(bool enableAnnotation)
+ public async Task OperationRestrictionsTermWorksToCreateOperationForEdmFunctionImport(bool enableAnnotation)
{
string template = @"
@@ -267,7 +281,7 @@ public void OperationRestrictionsTermWorksToCreateOperationForEdmFunctionImport(
{
Assert.Equal(2, operation.Security.Count);
- string json = operation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs
index b83e414b4..119172dfc 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs
@@ -5,12 +5,14 @@
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -18,7 +20,18 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EdmFunctionOperationHandlerTests
{
- private EdmFunctionOperationHandler _operationHandler = new();
+ public EdmFunctionOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+
+ private static EdmFunctionOperationHandler _operationHandler => new();
#region OperationHandlerTests
[Fact]
public void SetsDeprecationInformation()
@@ -94,6 +107,7 @@ public void CreateOperationForEdmFunctionReturnsCorrectOperation(bool useHTTPSta
// Act
var operation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(operation);
@@ -131,6 +145,7 @@ public void CreateOperationForEdmFunctionReturnsCorrectOperationHierarchicalClas
// Act
var operation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(operation);
@@ -395,7 +410,7 @@ public void CreateOperationForComposableOverloadEdmFunctionReturnsCorrectOperati
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void OperationRestrictionsTermWorksToCreateOperationForEdmFunction(bool enableAnnotation)
+ public async Task OperationRestrictionsTermWorksToCreateOperationForEdmFunction(bool enableAnnotation)
{
string template = @"
@@ -480,7 +495,7 @@ public void OperationRestrictionsTermWorksToCreateOperationForEdmFunction(bool e
{
Assert.Equal(2, operation.Security.Count);
- string json = operation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await operation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityDeleteOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityDeleteOperationHandlerTests.cs
index 8e3590869..cd6ffef99 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityDeleteOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityDeleteOperationHandlerTests.cs
@@ -4,9 +4,12 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -14,7 +17,17 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EntityDeleteOperationHandlerTests
{
- private EntityDeleteOperationHandler _operationHandler = new EntityDeleteOperationHandler();
+ public EntityDeleteOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+ private static EntityDeleteOperationHandler _operationHandler => new ();
[Theory]
[InlineData(true)]
@@ -33,6 +46,7 @@ public void CreateEntityDeleteOperationReturnsCorrectOperation(bool enableOperat
// Act
var delete = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(delete);
@@ -64,7 +78,7 @@ public void CreateEntityDeleteOperationReturnsCorrectOperation(bool enableOperat
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEntityDeleteReturnsSecurityForDeleteRestrictions(bool enableAnnotation)
+ public async Task CreateEntityDeleteReturnsSecurityForDeleteRestrictions(bool enableAnnotation)
{
string annotation = @"
@@ -140,7 +154,7 @@ public void CreateEntityDeleteReturnsSecurityForDeleteRestrictions(bool enableAn
{
Assert.Equal(2, delete.Security.Count);
- string json = delete.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await delete.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs
index b5d275ed4..aa847e07c 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityGetOperationHandlerTests.cs
@@ -5,9 +5,12 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -15,7 +18,18 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EntityGetOperationHandlerTests
{
- private EntityGetOperationHandler _operationHandler = new EntityGetOperationHandler();
+ public EntityGetOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+
+ private static EntityGetOperationHandler _operationHandler => new ();
[Theory]
[InlineData(true, true)]
@@ -37,6 +51,8 @@ public void CreateEntityGetOperationReturnsCorrectOperation(bool enableOperation
// Act
var get = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
+
// Assert
Assert.NotNull(get);
@@ -110,7 +126,7 @@ public void CreateEntityGetOperationReturnsParameterForNavigationRestrictions(bo
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEntityGetOperationReturnsSecurityForReadRestrictions(bool enableAnnotation)
+ public async Task CreateEntityGetOperationReturnsSecurityForReadRestrictions(bool enableAnnotation)
{
string annotation = @"
@@ -190,7 +206,7 @@ public void CreateEntityGetOperationReturnsSecurityForReadRestrictions(bool enab
{
Assert.Equal(2, get.Security.Count);
- string json = get.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await get.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs
index 5534a8713..059e022be 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPatchOperationHandlerTests.cs
@@ -4,9 +4,12 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -14,7 +17,18 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EntityPatchOperationHandlerTests
{
- private EntityPatchOperationHandler _operationHandler = new EntityPatchOperationHandler();
+ public EntityPatchOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+
+ private static EntityPatchOperationHandler _operationHandler => new ();
[Theory]
[InlineData(true, true)]
@@ -36,6 +50,7 @@ public void CreateEntityPatchOperationReturnsCorrectOperation(bool enableOperati
// Act
var patch = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(patch);
@@ -77,7 +92,7 @@ public void CreateEntityPatchOperationReturnsCorrectOperation(bool enableOperati
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEntityPatchReturnsSecurityForUpdateRestrictions(bool enableAnnotation)
+ public async Task CreateEntityPatchReturnsSecurityForUpdateRestrictions(bool enableAnnotation)
{
string annotation = @"
@@ -153,7 +168,7 @@ public void CreateEntityPatchReturnsSecurityForUpdateRestrictions(bool enableAnn
{
Assert.Equal(2, patch.Security.Count);
- string json = patch.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await patch.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs
index 96634cd4c..fe506becd 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntityPutOperationHandlerTests.cs
@@ -4,9 +4,12 @@
// ------------------------------------------------------------
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -14,7 +17,18 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EntityPutOperationHandlerTests
{
- private EntityPutOperationHandler _operationHandler = new EntityPutOperationHandler();
+ public EntityPutOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+
+ private static EntityPutOperationHandler _operationHandler => new();
[Theory]
[InlineData(true, true)]
@@ -36,6 +50,7 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation
// Act
var putOperation = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(putOperation);
@@ -77,7 +92,7 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEntityPutReturnsSecurityForUpdateRestrictions(bool enableAnnotation)
+ public async Task CreateEntityPutReturnsSecurityForUpdateRestrictions(bool enableAnnotation)
{
string annotation = @"
@@ -153,7 +168,7 @@ public void CreateEntityPutReturnsSecurityForUpdateRestrictions(bool enableAnnot
{
Assert.Equal(2, putOperation.Security.Count);
- string json = putOperation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await putOperation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs
index 74e270fec..2aa31da5a 100644
--- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs
+++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs
@@ -5,12 +5,16 @@
using System;
using System.Linq;
+using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OpenApi.Extensions;
+using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
+using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Tests;
using Xunit;
@@ -18,7 +22,18 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
{
public class EntitySetGetOperationHandlerTests
{
- private EntitySetGetOperationHandler _operationHandler = new EntitySetGetOperationHandler();
+ public EntitySetGetOperationHandlerTests()
+ {
+ _openApiDocument.AddComponent("Delegated (work or school account)", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ _openApiDocument.AddComponent("Application", new OpenApiSecurityScheme {
+ Type = SecuritySchemeType.OAuth2,
+ });
+ }
+ private readonly OpenApiDocument _openApiDocument = new();
+
+ private static EntitySetGetOperationHandler _operationHandler => new();
[Theory]
[InlineData(true, true, true)]
@@ -41,6 +56,7 @@ public void CreateEntitySetGetOperationReturnsCorrectOperation(bool enableOperat
// Act
var get = _operationHandler.CreateOperation(context, path);
+ _openApiDocument.Tags = context.CreateTags();
// Assert
Assert.NotNull(get);
@@ -227,7 +243,7 @@ public void CreateEntitySetGetOperationReturnsParameterForNavigationRestrictions
[Theory]
[InlineData(true)]
[InlineData(false)]
- public void CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool enableAnnotation)
+ public async Task CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool enableAnnotation)
{
string annotation = @"
@@ -303,7 +319,7 @@ public void CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool e
{
Assert.Equal(2, get.Security.Count);
- string json = get.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
+ string json = await get.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_0);
Assert.Contains(@"
""security"": [
{
@@ -435,7 +451,7 @@ private void VerifyParameter(string annotation, bool hasRestriction, bool suppor
Assert.Equal(8, get.Parameters.Count);
if (isReference)
{
- Assert.Contains(queryOption, get.Parameters.Select(p => p.Reference?.Id));
+ Assert.Contains(queryOption, get.Parameters.OfType