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..b3cdf8ed4 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;
@@ -21,7 +23,7 @@ internal static class EdmModelHelper
/// Adds the derived types references together with their base type reference in the OneOf property of an OpenAPI schema.
///
/// The OpenAPI schema with the list of derived types references and their base type references set in the OneOf property.
- internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel)
+ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel, OpenApiDocument document)
{
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
Utils.CheckArgumentNull(edmModel, nameof(edmModel));
@@ -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(), document);
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(), document);
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..5d5e6ca7e 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,10 +23,12 @@ 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)
+ /// The OpenAPI document to lookup references.
+ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiConvertSettings settings, OpenApiDocument document, bool addNoContent = false, IOpenApiSchema schema = null)
{
Utils.CheckArgumentNull(operation, nameof(operation));
Utils.CheckArgumentNull(settings, nameof(settings));
+ Utils.CheckArgumentNull(document, nameof(document));
if (operation.Responses == null)
{
@@ -54,22 +57,22 @@ public static void AddErrorResponses(this OpenApiOperation operation, OpenApiCon
}
};
}
- operation.Responses.Add(Constants.StatusCodeClass2XX, response ?? Constants.StatusCodeClass2XX.GetResponse());
+ operation.Responses.Add(Constants.StatusCodeClass2XX, response ?? Constants.StatusCodeClass2XX.GetResponse(document));
}
else
{
- operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse());
+ operation.Responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse(document));
}
}
if (settings.ErrorResponsesAsDefault)
{
- operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
+ operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse(document));
}
else
{
- operation.Responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse());
- operation.Responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse());
+ operation.Responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse(document));
+ operation.Responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse(document));
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs
index d653de0ea..d5db7aa58 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 is not null && attributesValueMap.Count > 0)
{
- 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..8f60d1876 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 OperationHandlerProvider();
+ PathItemHandlerProvider = 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..273ae47f4 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiDocumentGenerator.cs
@@ -32,24 +32,21 @@ 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
+
return doc;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiEdmTypeSchemaGenerator.cs
index 1144abf3e..50b7b1059 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,16 +23,28 @@ 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 Open API document to lookup references.
+ /// The created .
+ public static IOpenApiSchema CreateEdmTypeSchemaForParameter(this ODataContext context, IEdmTypeReference edmTypeReference, OpenApiDocument document)
+ => CreateEdmTypeSchema(context, edmTypeReference, document, true);
///
/// Create a for a .
///
/// The OData context.
/// The Edm type reference.
+ /// The Open API document to lookup references.
+ /// 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, OpenApiDocument document, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(edmTypeReference, nameof(edmTypeReference));
+ Utils.CheckArgumentNull(document, nameof(document));
switch (edmTypeReference.TypeKind())
{
@@ -39,14 +53,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
- ? context.CreateStructuredTypeSchema(typeRef.AsStructured(), true)
- : context.CreateEdmTypeSchema(typeRef);
+ var schema = typeRef.TypeKind() == EdmTypeKind.Complex || typeRef.TypeKind() == EdmTypeKind.Entity
+ ? context.CreateStructuredTypeSchema(typeRef.AsStructured(), document, true)
+ : context.CreateEdmTypeSchema(typeRef, document, schemaForParameter);
return new OpenApiSchema
{
- Type = "array",
+ Type = JsonSchemaType.Array,
Items = schema
};
@@ -55,22 +68,22 @@ public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmT
// or as external references for types defined in referenced CSDL documents.
case EdmTypeKind.Complex:
case EdmTypeKind.Entity:
- return context.CreateStructuredTypeSchema(edmTypeReference.AsStructured());
+ return context.CreateStructuredTypeSchema(edmTypeReference.AsStructured(), document);
case EdmTypeKind.Enum:
- return context.CreateEnumTypeSchema(edmTypeReference.AsEnum());
+ return context.CreateEnumTypeSchema(edmTypeReference.AsEnum(), document);
// Primitive properties of type Edm.PrimitiveType, Edm.Stream, and any of the Edm.Geo* types are
// 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, document, schemaForParameter);
case EdmTypeKind.TypeDefinition:
- return context.CreateSchema(((IEdmTypeDefinitionReference)edmTypeReference).TypeDefinition().UnderlyingType);
+ return context.CreateSchema(((IEdmTypeDefinitionReference)edmTypeReference).TypeDefinition().UnderlyingType, document, schemaForParameter);
case EdmTypeKind.EntityReference:
- return context.CreateTypeDefinitionSchema(edmTypeReference.AsTypeDefinition());
+ return context.CreateTypeDefinitionSchema(edmTypeReference.AsTypeDefinition(), document);
case EdmTypeKind.Untyped:
return new OpenApiSchema();
@@ -82,24 +95,27 @@ 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)
+ /// The Open API document to lookup references.
+ /// Whether the schema is for a parameter.
+ /// The created .
+ public static IOpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiveTypeReference primitiveType, OpenApiDocument document, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
+ Utils.CheckArgumentNull(document, nameof(document));
- OpenApiSchema schema = context.CreateSchema(primitiveType.PrimitiveDefinition());
- if (schema != null)
+ var schema = context.CreateSchema(primitiveType.PrimitiveDefinition(), document, 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 +127,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,11 +164,14 @@ public static OpenApiSchema CreateSchema(this ODataContext context, IEdmPrimitiv
///
/// The OData context.
/// The Edm primitive type.
+ /// The Open API document to lookup references.
+ /// 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, OpenApiDocument document, bool schemaForParameter = false)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(primitiveType, nameof(primitiveType));
+ Utils.CheckArgumentNull(document, nameof(document));
// Spec has different configure for double, AnyOf or OneOf?
OpenApiSchema schema = new OpenApiSchema
@@ -159,261 +181,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, document)
+ ];
+ 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, document)
+ ];
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", document);
case EdmPrimitiveTypeKind.GeographyPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyPoint", document);
case EdmPrimitiveTypeKind.GeographyLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyLineString", document);
case EdmPrimitiveTypeKind.GeographyPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyPolygon", document);
case EdmPrimitiveTypeKind.GeographyCollection:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyCollection"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyCollection", document);
case EdmPrimitiveTypeKind.GeographyMultiPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiPolygon", document);
case EdmPrimitiveTypeKind.GeographyMultiLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiLineString", document);
case EdmPrimitiveTypeKind.GeographyMultiPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeographyMultiPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeographyMultiPoint", document);
case EdmPrimitiveTypeKind.Geometry: // Geometry
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.Geometry"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.Geometry", document);
case EdmPrimitiveTypeKind.GeometryPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryPoint", document);
case EdmPrimitiveTypeKind.GeometryLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryLineString", document);
case EdmPrimitiveTypeKind.GeometryPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryPolygon", document);
case EdmPrimitiveTypeKind.GeometryCollection:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryCollection"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryCollection", document);
case EdmPrimitiveTypeKind.GeometryMultiPolygon:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPolygon"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiPolygon", document);
case EdmPrimitiveTypeKind.GeometryMultiLineString:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiLineString"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiLineString", document);
case EdmPrimitiveTypeKind.GeometryMultiPoint:
- schema.Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPoint"
- };
- schema.UnresolvedReference = true;
- break;
+ return new OpenApiSchemaReference("Edm.GeometryMultiPoint", document);
case EdmPrimitiveTypeKind.None:
default:
@@ -423,56 +336,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, OpenApiDocument document)
{
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(), document),
+ 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(), document);
}
-
- return schema;
}
- private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredTypeReference typeReference, bool isTypeCollection = false)
+ private static IOpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredTypeReference typeReference, OpenApiDocument document, bool isTypeCollection = false)
{
Debug.Assert(context != null);
Debug.Assert(typeReference != null);
-
- OpenApiSchema schema = new OpenApiSchema();
+ Debug.Assert(document != null);
// AnyOf will only be valid openApi for version 3
// otherwise the reference should be set directly
@@ -481,84 +374,46 @@ 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(), document),
+ 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(), document);
}
-
- return schema;
}
- private static OpenApiSchema CreateTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinitionReference reference)
+ private static IOpenApiSchema CreateTypeDefinitionSchema(this ODataContext context, IEdmTypeDefinitionReference reference, OpenApiDocument document)
{
Debug.Assert(context != null);
Debug.Assert(reference != null);
-
- OpenApiSchema schema = new OpenApiSchema();
- schema.Reference = null;
+ Debug.Assert(document != 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(), document),
+ 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(), document);
+ }
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiErrorSchemaGenerator.cs
index beeaa1d1d..346362259 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
{
@@ -30,18 +32,19 @@ internal static class OpenApiErrorSchemaGenerator
/// The value of each pair is a .
///
/// The OData to Open API context.
+ /// The Open API document to lookup references.
/// The string/schema dictionary.
- public static IDictionary CreateODataErrorSchemas(this ODataContext context)
+ public static IDictionary CreateODataErrorSchemas(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
var rootNamespaceName = context.GetErrorNamespaceName();
- return new Dictionary()
+ return new Dictionary()
{
- { $"{rootNamespaceName}{ODataErrorClassName}", CreateErrorSchema(rootNamespaceName) },
- { $"{rootNamespaceName}{MainErrorClassName}", CreateErrorMainSchema(rootNamespaceName) },
+ { $"{rootNamespaceName}{ODataErrorClassName}", CreateErrorSchema(rootNamespaceName, document) },
+ { $"{rootNamespaceName}{MainErrorClassName}", CreateErrorMainSchema(rootNamespaceName, document) },
{ $"{rootNamespaceName}{ErrorDetailsClassName}", CreateErrorDetailSchema() },
- { $"{rootNamespaceName}{InnerErrorClassName}", CreateInnerErrorSchema(context) }
+ { $"{rootNamespaceName}{InnerErrorClassName}", CreateInnerErrorSchema(context, document) }
};
}
@@ -63,28 +66,21 @@ public static string GetErrorNamespaceName(this ODataContext context) {
///
/// The created .
/// The root namespace name. With a trailing dot.
- public static OpenApiSchema CreateErrorSchema(string rootNamespaceName)
+ /// The Open API document to lookup references.
+ public static OpenApiSchema CreateErrorSchema(string rootNamespaceName, OpenApiDocument document)
{
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}", document)
}
}
};
@@ -95,8 +91,9 @@ public static OpenApiSchema CreateErrorSchema(string rootNamespaceName)
/// Otherwise, a default inner error type of object will be created.
///
/// The OData to Open API context.
+ /// The Open API document to lookup references.
/// The inner error schema definition.
- public static OpenApiSchema CreateInnerErrorSchema(ODataContext context)
+ public static IOpenApiSchema CreateInnerErrorSchema(ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
@@ -105,12 +102,12 @@ public static OpenApiSchema CreateInnerErrorSchema(ODataContext context)
!string.IsNullOrEmpty(rootNamespace) &&
context.Model.FindDeclaredType($"{rootNamespace}.{context.Settings.InnerErrorComplexTypeName}") is IEdmComplexType complexType)
{
- return context.CreateSchemaTypeSchema(complexType);
+ return context.CreateSchemaTypeSchema(complexType, document);
}
return new OpenApiSchema
{
- Type = "object",
+ Type = JsonSchemaType.Object,
Description = "The structure of this object is service-specific"
};
}
@@ -119,55 +116,40 @@ public static OpenApiSchema CreateInnerErrorSchema(ODataContext context)
/// Create for main property of the error.
///
/// The root namespace name. With a trailing dot.
+ /// The Open API document to lookup references.
/// The created .
- public static OpenApiSchema CreateErrorMainSchema(string rootNamespaceName)
+ public static OpenApiSchema CreateErrorMainSchema(string rootNamespaceName, OpenApiDocument document)
{
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}", document)
}
},
{
"innerError",
- new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = $"{rootNamespaceName}{InnerErrorClassName}"
- }
- }
+ new OpenApiSchemaReference($"{rootNamespaceName}{InnerErrorClassName}", document)
}
}
};
@@ -181,21 +163,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..fc315fdcb 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,167 +23,44 @@ 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, document) 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)
+ private static OpenApiExample CreateExample(this ODataContext context, IEdmType edmType, OpenApiDocument document)
{
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, document),
+ },
+ _ => 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..dad145a3d 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());
}
///
@@ -49,13 +50,15 @@ public static IDictionary CreateParameters(this ODataC
///
/// The OData context.
/// The Edm function import.
+ /// The Open API document to lookup references.
/// The created list of .
- public static IList CreateParameters(this ODataContext context, IEdmFunctionImport functionImport)
+ public static IList CreateParameters(this ODataContext context, IEdmFunctionImport functionImport, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(functionImport, nameof(functionImport));
+ Utils.CheckArgumentNull(document, nameof(document));
- return context.CreateParameters(functionImport.Function);
+ return context.CreateParameters(functionImport.Function, document);
}
///
@@ -63,25 +66,25 @@ public static IList CreateParameters(this ODataContext context
///
/// The OData context.
/// The Edm function.
+ /// The Open API document to lookup references.
/// 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,
+ OpenApiDocument document,
IDictionary parameterNameMapping = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(function, nameof(function));
+ Utils.CheckArgumentNull(document, nameof(document));
- 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 +106,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 +132,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, document)
};
}
@@ -152,16 +155,19 @@ public static IList CreateParameters(this ODataContext context
///
/// The OData context.
/// The key segment.
+ /// The Open API document to lookup references.
/// The parameter name mapping.
/// The created list of .
public static IList CreateKeyParameters(this ODataContext context, ODataKeySegment keySegment,
+ OpenApiDocument document,
IDictionary parameterNameMapping = null)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(keySegment, nameof(keySegment));
+ Utils.CheckArgumentNull(document, nameof(document));
if (keySegment.IsAlternateKey)
- return CreateAlternateKeyParameters(context, keySegment);
+ return CreateAlternateKeyParameters(context, keySegment, document);
IEdmEntityType entityType = keySegment.EntityType;
IList keys = entityType.Key().ToList();
@@ -184,10 +190,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, document)
};
- parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name));
+ parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiAny(entityType.Name));
parameters.Add(parameter);
}
else
@@ -203,7 +209,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, document)
};
if (keySegment.KeyMappings != null)
@@ -212,7 +218,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);
}
}
@@ -225,14 +231,15 @@ public static IList CreateKeyParameters(this ODataContext cont
///
/// The OData context.
/// The key segment.
+ /// The Open API document to lookup references.
/// A list of of alternate key parameters.
- private static IList CreateAlternateKeyParameters(ODataContext context, ODataSegment keySegment)
+ private static List CreateAlternateKeyParameters(ODataContext context, ODataKeySegment keySegment, OpenApiDocument document)
{
Debug.Assert(keySegment.Kind == ODataSegmentKind.Key);
- IList parameters = new List();
- IEdmEntityType entityType = keySegment.EntityType;
- IEnumerable> alternateKeys = context.Model.GetAlternateKeysAnnotation(entityType);
+ var parameters = new List();
+ var entityType = keySegment.EntityType;
+ var alternateKeys = context.Model.GetAlternateKeysAnnotation(entityType);
foreach (var alternateKey in alternateKeys)
{
@@ -246,7 +253,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, document),
Required = true
}
);
@@ -264,7 +271,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, document),
Required = true
}
);
@@ -280,16 +287,17 @@ private static IList CreateAlternateKeyParameters(ODataContext
///
/// The ODataPath
/// The OData context.
+ /// The Open API document to lookup references.
/// The created list of
- public static List CreatePathParameters(this ODataPath path, ODataContext context)
+ public static List CreatePathParameters(this ODataPath path, ODataContext context, OpenApiDocument document)
{
- List pathParameters = new();
+ List pathParameters = [];
var parameterMappings = path.CalculateParameterMapping(context.Settings);
foreach (ODataKeySegment keySegment in path.OfType())
{
IDictionary mapping = parameterMappings[keySegment];
- pathParameters.AddRange(context.CreateKeyParameters(keySegment, mapping));
+ pathParameters.AddRange(context.CreateKeyParameters(keySegment, document, mapping));
}
foreach (ODataOperationSegment operationSegment in path.OfType())
@@ -301,7 +309,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, document, operationSegment.ParameterMappings);
foreach (var parameter in parameters)
{
pathParameters.AppendParameter(parameter);
@@ -310,7 +318,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, document, mappings);
pathParameters.AddRange(parameters);
}
}
@@ -331,7 +339,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 +351,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);
}
@@ -353,20 +364,18 @@ public static void AppendParameter(this IList parameters, Open
///
/// The OData context.
/// The Edm annotation target.
+ /// The Open API document.
/// The created or null.
- public static OpenApiParameter CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateTop(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(document, nameof(document));
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", document);
}
return null;
@@ -377,17 +386,19 @@ public static OpenApiParameter CreateTop(this ODataContext context, IEdmVocabula
///
/// The OData context.
/// The string representation of the Edm target path.
+ /// The Open API document to use to build references.
///
- public static OpenApiParameter CreateTop(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateTop(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
+ Utils.CheckArgumentNull(document, nameof(document));
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
return null;
- return context.CreateTop(target);
+ return context.CreateTop(target, document);
}
///
@@ -395,20 +406,18 @@ public static OpenApiParameter CreateTop(this ODataContext context, string targe
///
/// The OData context.
/// The Edm annotation target.
+ /// The Open API document to use to build references.
/// The created or null.
- public static OpenApiParameter CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateSkip(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(document, nameof(document));
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", document);
}
return null;
@@ -419,17 +428,19 @@ public static OpenApiParameter CreateSkip(this ODataContext context, IEdmVocabul
///
/// The OData context.
/// The string representation of the Edm target path.
+ /// The Open API document to use to build references.
///
- public static OpenApiParameter CreateSkip(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateSkip(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
+ Utils.CheckArgumentNull(document, nameof(document));
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
return null;
- return context.CreateSkip(target);
+ return context.CreateSkip(target, document);
}
///
@@ -437,20 +448,18 @@ public static OpenApiParameter CreateSkip(this ODataContext context, string targ
///
/// The OData context.
/// The Edm annotation target.
+ /// The Open API document to use to build references.
/// The created or null.
- public static OpenApiParameter CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateSearch(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(document, nameof(document));
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", document);
}
return null;
@@ -460,17 +469,19 @@ public static OpenApiParameter CreateSearch(this ODataContext context, IEdmVocab
///
/// The OData context.
/// The string representation of the Edm target path.
+ /// The Open API document to use to build references.
///
- public static OpenApiParameter CreateSearch(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateSearch(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
+ Utils.CheckArgumentNull(document, nameof(document));
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
return null;
- return context.CreateSearch(target);
+ return context.CreateSearch(target, document);
}
///
@@ -478,20 +489,18 @@ public static OpenApiParameter CreateSearch(this ODataContext context, string ta
///
/// The OData context.
/// The Edm annotation target.
+ /// The Open API document to use to build references.
/// The created or null.
- public static OpenApiParameter CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateCount(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(document, nameof(document));
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", document);
}
return null;
@@ -502,17 +511,19 @@ public static OpenApiParameter CreateCount(this ODataContext context, IEdmVocabu
///
/// The OData context.
/// The string representation of the Edm target path.
+ /// The Open API document to use to build references.
///
- public static OpenApiParameter CreateCount(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateCount(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
+ Utils.CheckArgumentNull(document, nameof(document));
IEdmTargetPath target = context.Model.GetTargetPath(targetPath);
if (target == null)
return null;
- return context.CreateCount(target);
+ return context.CreateCount(target, document);
}
///
@@ -520,20 +531,18 @@ public static OpenApiParameter CreateCount(this ODataContext context, string tar
///
/// The OData context.
/// The Edm annotation target.
+ /// The Open API document to use to build references.
/// The created or null.
- public static OpenApiParameter CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target)
+ public static IOpenApiParameter CreateFilter(this ODataContext context, IEdmVocabularyAnnotatable target, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(target, nameof(target));
+ Utils.CheckArgumentNull(document, nameof(document));
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", document);
}
return null;
@@ -544,8 +553,9 @@ public static OpenApiParameter CreateFilter(this ODataContext context, IEdmVocab
///
/// The OData context.
/// The string representation of the Edm target path.
+ /// The Open API document to use to build references.
///
- public static OpenApiParameter CreateFilter(this ODataContext context, string targetPath)
+ public static IOpenApiParameter CreateFilter(this ODataContext context, string targetPath, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(targetPath, nameof(targetPath));
@@ -554,7 +564,7 @@ public static OpenApiParameter CreateFilter(this ODataContext context, string ta
if (target == null)
return null;
- return context.CreateFilter(target);
+ return context.CreateFilter(target, document);
}
public static OpenApiParameter CreateOrderBy(this ODataContext context, string targetPath, IEdmEntityType entityType)
@@ -626,7 +636,7 @@ public static OpenApiParameter CreateOrderBy(this ODataContext context, IEdmVoca
return null;
}
- IList orderByItems = new List();
+ var orderByItems = new List();
foreach (var property in structuredType.StructuralProperties())
{
if (sort != null && sort.IsNonSortableProperty(property.Name))
@@ -640,17 +650,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 +671,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 +753,11 @@ public static OpenApiParameter CreateSelect(this ODataContext context, IEdmVocab
return null;
}
- IList selectItems = new List();
+ var 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 +767,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 +777,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 +859,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 +868,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 +878,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 +901,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 +921,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 +940,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 +957,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 +974,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..604b5676a 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, document);
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 Dictionary 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..ffb8f0c10 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
{
@@ -22,13 +24,15 @@ internal static class OpenApiRequestBodyGenerator
///
/// The OData context.
/// The Edm action import.
+ /// The OpenApi document to lookup references.
/// The created or null.
- public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmActionImport actionImport)
+ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmActionImport actionImport, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(actionImport, nameof(actionImport));
+ Utils.CheckArgumentNull(document, nameof(document));
- return context.CreateRequestBody(actionImport.Action);
+ return context.CreateRequestBody(actionImport.Action, document);
}
///
@@ -36,11 +40,13 @@ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IE
///
/// The OData context.
/// The Edm action.
+ /// The OpenApi document to lookup references.
/// The created or null.
- public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmAction action)
+ public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmAction action, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(action, nameof(action));
+ Utils.CheckArgumentNull(document, nameof(document));
// return null for empty action parameters
int skip = 0;
@@ -62,13 +68,13 @@ 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))
{
- parametersSchema.Properties.Add(parameter.Name, context.CreateEdmTypeSchema(parameter.Type));
+ parametersSchema.Properties.Add(parameter.Name, context.CreateEdmTypeSchema(parameter.Type, document));
}
OpenApiRequestBody requestBody = new OpenApiRequestBody
@@ -90,50 +96,32 @@ 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));
+ document.AddComponent(Constants.ReferencePutRequestBodyName, CreateRefPutRequestBody(document));
// 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, document) is OpenApiRequestBody requestBody)
+ document.AddComponent($"{action.Name}RequestBody", requestBody);
}
-
- return requestBodies;
}
///
/// Create a to be reused across ref POST operations
///
/// The created
- private static OpenApiRequestBody CreateRefPostRequestBody()
+ /// The OpenApi document to lookup references.
+ private static OpenApiRequestBody CreateRefPostRequestBody(OpenApiDocument document)
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceCreateSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.ReferenceCreateSchemaName, document);
return new OpenApiRequestBody
{
Required = true,
@@ -154,17 +142,10 @@ private static OpenApiRequestBody CreateRefPostRequestBody()
/// Create a to be reused across ref PUT operations
///
/// The created
- private static OpenApiRequestBody CreateRefPutRequestBody()
+ /// The OpenApi document to lookup references.
+ private static OpenApiRequestBody CreateRefPutRequestBody(OpenApiDocument document)
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = Constants.ReferenceUpdateSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.ReferenceUpdateSchemaName, document);
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..c0cfa4f01 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiResponseGenerator.cs
@@ -3,10 +3,14 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
+using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
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 +22,23 @@ 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 OpenApi document to lookup references.
+ /// The created .
+ public static IOpenApiResponse GetResponse(this string statusCode, OpenApiDocument document)
{
- if (_responses.TryGetValue(statusCode, out OpenApiResponse response))
- {
- return response;
- }
-
- return null;
+ return statusCode switch {
+ Constants.StatusCodeDefault => new OpenApiResponseReference(Constants.Error, document),
+ 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, document),
+ Constants.StatusCodeClass5XX => new OpenApiResponseReference(Constants.Error, document),
+ _ => null,
+ };
}
///
@@ -80,45 +48,49 @@ 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
{
- { "error", context.CreateErrorResponse() }
+ { "error", context.CreateErrorResponse(document) }
};
if(context.Settings.EnableDollarCountPath)
{
- responses[Constants.DollarCountSchemaName] = CreateCountResponse();
+ responses[Constants.DollarCountSchemaName] = CreateCountResponse(document);
}
responses = responses.Concat(context.GetAllCollectionEntityTypes()
.Select(x => new KeyValuePair(
$"{(x is IEdmEntityType eType ? eType.FullName() : x.FullTypeName())}{Constants.CollectionSchemaSuffix}",
- CreateCollectionResponse(x)))
+ CreateCollectionResponse(x, document)))
.Where(x => !responses.ContainsKey(x.Key)))
.Concat(context.GetAllCollectionComplexTypes()
.Select(x => new KeyValuePair(
$"{x.FullTypeName()}{Constants.CollectionSchemaSuffix}",
- CreateCollectionResponse(x)))
+ CreateCollectionResponse(x, document)))
.Where(x => !responses.ContainsKey(x.Key)))
.ToDictionary(x => x.Key, x => x.Value);
if(context.HasAnyNonContainedCollections())
- responses[$"String{Constants.CollectionSchemaSuffix}"] = CreateCollectionResponse("String");
+ responses[$"String{Constants.CollectionSchemaSuffix}"] = CreateCollectionResponse("String", document);
foreach (IEdmOperation operation in context.Model.SchemaElements.OfType()
.Where(op => context.Model.OperationTargetsMultiplePaths(op)))
{
- OpenApiResponse response = context.CreateOperationResponse(operation);
+ OpenApiResponse response = context.CreateOperationResponse(operation, document);
if (response != null)
responses[$"{operation.Name}Response"] = response;
}
- return responses;
+ foreach (var response in responses)
+ {
+ document.AddComponent(response.Key, response.Value);
+ }
}
///
@@ -126,13 +98,15 @@ public static IDictionary CreateResponses(this ODataCon
///
/// The OData context.
/// The Edm operation import.
+ /// The OpenApi document to lookup references.
/// The created .
- public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperationImport operationImport)
+ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperationImport operationImport, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(operationImport, nameof(operationImport));
+ Utils.CheckArgumentNull(document, nameof(document));
- return context.CreateResponses(operationImport.Operation);
+ return context.CreateResponses(operationImport.Operation, document);
}
///
@@ -140,8 +114,9 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
///
/// The OData context.
/// The Edm operation.
+ /// The OpenApi document to lookup references.
/// The created .
- public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation)
+ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(operation, nameof(operation));
@@ -150,57 +125,49 @@ public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOp
if (operation.IsAction() && operation.ReturnType == null)
{
- responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse());
+ responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse(document));
}
else if (context.Model.OperationTargetsMultiplePaths(operation))
{
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", document)
);
}
else
{
- OpenApiResponse response = context.CreateOperationResponse(operation);
+ OpenApiResponse response = context.CreateOperationResponse(operation, document);
responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response);
}
if (context.Settings.ErrorResponsesAsDefault)
{
- responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
+ responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse(document));
}
else
{
- responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse());
- responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse());
+ responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse(document));
+ responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse(document));
}
return responses;
}
- public static OpenApiResponse CreateOperationResponse(this ODataContext context, IEdmOperation operation)
+ public static OpenApiResponse CreateOperationResponse(this ODataContext context, IEdmOperation operation, OpenApiDocument document)
{
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)
+ "value", context.CreateEdmTypeSchema(operation.ReturnType, document)
}
}
};
@@ -210,20 +177,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)
+ ,document),
baseSchema
- }
+ ]
};
}
else if (operation.IsDeltaFunction())
@@ -245,9 +205,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,18 +218,18 @@ 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)
+ "value", context.CreateEdmTypeSchema(operation.ReturnType, document)
}
}
};
}
else
{
- schema = context.CreateEdmTypeSchema(operation.ReturnType);
+ schema = context.CreateEdmTypeSchema(operation.ReturnType, document);
}
string mediaType = Constants.ApplicationJsonMediaType;
@@ -299,12 +262,12 @@ public static OpenApiResponse CreateOperationResponse(this ODataContext context,
return response;
}
- private static OpenApiResponse CreateCollectionResponse(IEdmStructuredType structuredType)
+ private static OpenApiResponse CreateCollectionResponse(IEdmStructuredType structuredType, OpenApiDocument document)
{
var entityType = structuredType as IEdmEntityType;
- return CreateCollectionResponse(entityType?.FullName() ?? structuredType.FullTypeName());
+ return CreateCollectionResponse(entityType?.FullName() ?? structuredType.FullTypeName(), document);
}
- private static OpenApiResponse CreateCollectionResponse(string typeName)
+ private static OpenApiResponse CreateCollectionResponse(string typeName, OpenApiDocument document)
{
return new OpenApiResponse
{
@@ -315,31 +278,16 @@ 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}", document)
}
}
}
};
}
- private static OpenApiResponse CreateCountResponse()
+ private static OpenApiResponse CreateCountResponse(OpenApiDocument document)
{
- OpenApiSchema schema = new()
- {
- UnresolvedReference = true,
- Reference = new() {
- Type = ReferenceType.Schema,
- Id = Constants.DollarCountSchemaName
- }
- };
+ var schema = new OpenApiSchemaReference(Constants.DollarCountSchemaName, document);
return new OpenApiResponse
{
Description = "The count of the resource",
@@ -356,7 +304,7 @@ private static OpenApiResponse CreateCountResponse()
};
}
- private static OpenApiResponse CreateErrorResponse(this ODataContext context)
+ private static OpenApiResponse CreateErrorResponse(this ODataContext context, OpenApiDocument document)
{
var errorNamespaceName = context.GetErrorNamespaceName();
return new OpenApiResponse
@@ -368,15 +316,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}", document)
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSchemaGenerator.cs
index 2834322ed..e84a7e914 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())
+ foreach(var schema in context.CreateSpatialSchemas(document))
{
- schemas[schema.Key] = schema.Value;
+ document.AddComponent(schema.Key, schema.Value);
}
// append the OData errors
- foreach(var schema in context.CreateODataErrorSchemas())
+ foreach(var schema in context.CreateODataErrorSchemas(document))
{
- 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, document));
}
- 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, document));
+ }
+ 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, document)))
+ .Concat(context.GetAllCollectionComplexTypes()
+ .Select(x => new KeyValuePair(
+ $"{x.FullTypeName()}{Constants.CollectionSchemaSuffix}",
+ CreateCollectionSchema(context, x, document))))
+ .ToArray())
+ {
+ document.AddComponent(collectionEntry.Key, collectionEntry.Value);
+ }
}
internal static bool HasAnyNonContainedCollections(this ODataContext context)
{
@@ -204,39 +208,31 @@ internal static IEnumerable GetAllCollectionEntityTypes(this
return collectionEntityTypes.Union(derivedCollectionTypes);
}
- private static OpenApiSchema CreateCollectionSchema(ODataContext context, IEdmStructuredType structuredType)
+ private static OpenApiSchema CreateCollectionSchema(ODataContext context, IEdmStructuredType structuredType, OpenApiDocument document)
{
- OpenApiSchema schema = null;
+ IOpenApiSchema schema = null;
var entityType = structuredType as IEdmEntityType;
if (context.Settings.EnableDerivedTypesReferencesForResponses && entityType != null)
{
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, context.Model);
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, context.Model, document);
}
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(), document);
}
- return CreateCollectionSchema(context, schema, entityType?.Name ?? structuredType.FullTypeName());
+ return CreateCollectionSchema(context, schema, entityType?.Name ?? structuredType.FullTypeName(), document);
}
- private static OpenApiSchema CreateCollectionSchema(ODataContext context, OpenApiSchema schema, string typeName)
+ private static OpenApiSchema CreateCollectionSchema(ODataContext context, IOpenApiSchema schema, string typeName, OpenApiDocument document)
{
- 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, document);
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);
}
@@ -370,13 +359,15 @@ private static void AddEnumDescription(IEdmEnumMember member, OpenApiEnumValuesD
///
/// The OData context.
/// The Edm structured type.
+ /// The Open API document to lookup references.
/// The created .
- public static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType)
+ public static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
+ Utils.CheckArgumentNull(document, nameof(document));
- return context.CreateStructuredTypeSchema(structuredType, true, true);
+ return context.CreateStructuredTypeSchema(structuredType, true, true, document);
}
///
@@ -387,28 +378,32 @@ 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 Open API document to lookup references.
+ /// The created .
+ public static IOpenApiSchema CreatePropertySchema(this ODataContext context, IEdmProperty property, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
Utils.CheckArgumentNull(property, nameof(property));
+ Utils.CheckArgumentNull(document, nameof(document));
- OpenApiSchema schema = context.CreateEdmTypeSchema(property.Type);
+ var schema = context.CreateEdmTypeSchema(property.Type, document);
- 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;
}
@@ -418,43 +413,54 @@ public static OpenApiSchema CreatePropertySchema(this ODataContext context, IEdm
///
/// The OData context.
/// The Edm structured type.
+ /// The Open API document to lookup references.
/// The created map of .
- public static IDictionary CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType)
+ public static IDictionary CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType, OpenApiDocument document)
{
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, document);
+ 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, document);
+ 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, OpenApiDocument document)
{
- return context.CreateSchema(typeDefinition.UnderlyingType);
+ return context.CreateSchema(typeDefinition.UnderlyingType, document);
}
- internal static OpenApiSchema CreateSchemaTypeSchema(this ODataContext context, IEdmType edmType)
+ internal static IOpenApiSchema CreateSchemaTypeSchema(this ODataContext context, IEdmType edmType, OpenApiDocument document)
{
Debug.Assert(context != null);
Debug.Assert(edmType != null);
@@ -463,30 +469,31 @@ internal static OpenApiSchema CreateSchemaTypeSchema(this ODataContext context,
{
case EdmTypeKind.Complex: // complex type
case EdmTypeKind.Entity: // entity type
- return context.CreateStructuredTypeSchema((IEdmStructuredType)edmType, true, true);
+ return context.CreateStructuredTypeSchema((IEdmStructuredType)edmType, true, true, document);
case EdmTypeKind.Enum: // enum type
return context.CreateEnumTypeSchema((IEdmEnumType)edmType);
case EdmTypeKind.TypeDefinition: // type definition
- return context.CreateSchemaTypeDefinitionSchema((IEdmTypeDefinition)edmType);
+ return context.CreateSchemaTypeDefinitionSchema((IEdmTypeDefinition)edmType, document);
case EdmTypeKind.None:
default:
- throw Error.NotSupported(String.Format(SRResource.NotSupportedEdmTypeKind, edmType.TypeKind));
+ throw Error.NotSupported(string.Format(SRResource.NotSupportedEdmTypeKind, edmType.TypeKind));
}
}
private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext context, IEdmStructuredType structuredType, bool processBase, bool processExample,
+ OpenApiDocument document,
IEnumerable derivedTypes = null)
{
Debug.Assert(context != null);
Debug.Assert(structuredType != null);
- IOpenApiAny example = null;
+ JsonNode example = null;
if (context.Settings.ShowSchemaExamples)
{
- example = CreateStructuredTypePropertiesExample(context, structuredType);
+ example = CreateStructuredTypePropertiesExample(context, structuredType, document);
}
if (context.Settings.EnableDiscriminatorValue && derivedTypes == null)
@@ -502,7 +509,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 +519,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(), document),
// 2. a Schema Object describing the derived type
- context.CreateStructuredTypeSchema(structuredType, false, false, derivedTypes)
- },
+ context.CreateStructuredTypeSchema(structuredType, false, false, document, derivedTypes)
+ ],
AnyOf = null,
OneOf = null,
@@ -542,14 +541,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(), document).Reference.ReferenceV3);
discriminator = new OpenApiDiscriminator
{
@@ -563,13 +555,13 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
{
Title = (structuredType as IEdmSchemaElement)?.Name,
- Type = Constants.ObjectType,
+ Type = JsonSchemaType.Object,
Discriminator = discriminator,
// Each structural property and navigation property is represented
// as a name/value pair of the standard OpenAPI properties object.
- Properties = context.CreateStructuredTypePropertiesSchema(structuredType),
+ Properties = context.CreateStructuredTypePropertiesSchema(structuredType, document),
// make others null
AllOf = null,
@@ -579,7 +571,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 +579,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 +616,24 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
}
}
- private static IOpenApiAny CreateStructuredTypePropertiesExample(ODataContext context, IEdmStructuredType structuredType)
+ internal static JsonObject CreateStructuredTypePropertiesExample(ODataContext context, IEdmStructuredType structuredType, OpenApiDocument document)
{
- 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, document);
- 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 +642,65 @@ private static IOpenApiAny CreateStructuredTypePropertiesExample(ODataContext co
return example;
}
- private static IOpenApiAny GetTypeNameForExample(ODataContext context, IEdmTypeReference edmTypeReference)
+ private static JsonNode GetTypeNameForPrimitive(ODataContext context, IEdmTypeReference edmTypeReference, OpenApiDocument document)
{
- switch (edmTypeReference.TypeKind())
+ IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition();
+ IOpenApiSchema schema = context.CreateSchema(primitiveType, document);
+
+ if (edmTypeReference.IsBoolean())
+ {
+ return true;
+ }
+ else
{
- case EdmTypeKind.Primitive:
- IEdmPrimitiveType primitiveType = edmTypeReference.AsPrimitive().PrimitiveDefinition();
- OpenApiSchema schema = context.CreateSchema(primitiveType);
+ 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;
+ }
+ }
+ }
- if (edmTypeReference.IsBoolean())
- {
- return new OpenApiBoolean(true);
- }
- else
+ private static JsonNode GetTypeNameForExample(ODataContext context, IEdmTypeReference edmTypeReference, OpenApiDocument document)
+ {
+ 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, document),
+
+ EdmTypeKind.Entity or EdmTypeKind.Complex => new JsonObject()
{
- 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;
-
- case EdmTypeKind.Untyped:
- return new OpenApiObject();
-
- case EdmTypeKind.TypeDefinition:
- case EdmTypeKind.EntityReference:
- default:
- throw new OpenApiException("Not support for the type kind " + edmTypeReference.TypeKind());
- }
+ [Constants.OdataType] = edmTypeReference.FullName()
+ },
+ EdmTypeKind.Enum when edmTypeReference.Definition is IEdmEnumType edmEnumType && edmEnumType.Members.FirstOrDefault()?.Name is string firstMemberName =>
+ JsonValue.Create(firstMemberName),
+ EdmTypeKind.Collection => new JsonArray(GetTypeNameForExample(context, edmTypeReference.AsCollection().ElementType(), document)),
+ EdmTypeKind.TypeDefinition => GetTypeNameForExample(context, new EdmPrimitiveTypeReference(edmTypeReference.AsTypeDefinition().TypeDefinition().UnderlyingType, edmTypeReference.IsNullable), document),
+ 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 +710,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 +723,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 +733,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 +756,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..3aa231f98 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,49 +19,18 @@ 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.
///
/// The OData to Open API context.
/// The permissions.
+ /// The Open API document to use for references lookup.
/// The created collection.
public static IEnumerable CreateSecurityRequirements(this ODataContext context,
- IList permissions)
+ IList permissions, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
+ Utils.CheckArgumentNull(document, nameof(document));
if (permissions != null)
{
@@ -69,15 +39,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, document)
] = 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..74a70bf06 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;
@@ -22,46 +24,47 @@ internal static class OpenApiSpatialTypeSchemaGenerator
/// The value of each pair is a .
///
/// The OData to Open API context.
+ /// The document to use to lookup references.
/// The string/schema dictionary.
- public static IDictionary CreateSpatialSchemas(this ODataContext context)
+ public static IDictionary CreateSpatialSchemas(this ODataContext context, OpenApiDocument document)
{
Utils.CheckArgumentNull(context, nameof(context));
- IDictionary schemas = new Dictionary();
+ var schemas = new Dictionary();
if (context.IsSpatialTypeUsed)
{
- schemas.Add("Edm.Geography", CreateEdmGeographySchema());
+ schemas.Add("Edm.Geography", CreateEdmGeographySchema(document));
- schemas.Add("Edm.GeographyPoint", CreateEdmGeographyPointSchema());
+ schemas.Add("Edm.GeographyPoint", CreateEdmGeographyPointSchema(document));
- schemas.Add("Edm.GeographyLineString", CreateEdmGeographyLineStringSchema());
+ schemas.Add("Edm.GeographyLineString", CreateEdmGeographyLineStringSchema(document));
- schemas.Add("Edm.GeographyPolygon", CreateEdmGeographyPolygonSchema());
+ schemas.Add("Edm.GeographyPolygon", CreateEdmGeographyPolygonSchema(document));
- schemas.Add("Edm.GeographyMultiPoint", CreateEdmGeographyMultiPointSchema());
+ schemas.Add("Edm.GeographyMultiPoint", CreateEdmGeographyMultiPointSchema(document));
- schemas.Add("Edm.GeographyMultiLineString", CreateEdmGeographyMultiLineStringSchema());
+ schemas.Add("Edm.GeographyMultiLineString", CreateEdmGeographyMultiLineStringSchema(document));
- schemas.Add("Edm.GeographyMultiPolygon", CreateEdmGeographyMultiPolygonSchema());
+ schemas.Add("Edm.GeographyMultiPolygon", CreateEdmGeographyMultiPolygonSchema(document));
- schemas.Add("Edm.GeographyCollection", CreateEdmGeographyCollectionSchema());
+ schemas.Add("Edm.GeographyCollection", CreateEdmGeographyCollectionSchema(document));
- schemas.Add("Edm.Geometry", CreateEdmGeometrySchema());
+ schemas.Add("Edm.Geometry", CreateEdmGeometrySchema(document));
- schemas.Add("Edm.GeometryPoint", CreateEdmGeometryPointSchema());
+ schemas.Add("Edm.GeometryPoint", CreateEdmGeometryPointSchema(document));
- schemas.Add("Edm.GeometryLineString", CreateEdmGeometryLineStringSchema());
+ schemas.Add("Edm.GeometryLineString", CreateEdmGeometryLineStringSchema(document));
- schemas.Add("Edm.GeometryPolygon", CreateEdmGeometryPolygonSchema());
+ schemas.Add("Edm.GeometryPolygon", CreateEdmGeometryPolygonSchema(document));
- schemas.Add("Edm.GeometryMultiPoint", CreateEdmGeometryMultiPointSchema());
+ schemas.Add("Edm.GeometryMultiPoint", CreateEdmGeometryMultiPointSchema(document));
- schemas.Add("Edm.GeometryMultiLineString", CreateEdmGeometryMultiLineStringSchema());
+ schemas.Add("Edm.GeometryMultiLineString", CreateEdmGeometryMultiLineStringSchema(document));
- schemas.Add("Edm.GeometryMultiPolygon", CreateEdmGeometryMultiPolygonSchema());
+ schemas.Add("Edm.GeometryMultiPolygon", CreateEdmGeometryMultiPolygonSchema(document));
- schemas.Add("Edm.GeometryCollection", CreateEdmGeometryCollectionSchema());
+ schemas.Add("Edm.GeometryCollection", CreateEdmGeometryCollectionSchema(document));
schemas.Add("GeoJSON.position", CreateGeoJsonPointSchema());
}
@@ -73,157 +76,102 @@ public static IDictionary CreateSpatialSchemas(this OData
/// Create for Edm.Geography.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographySchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographySchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.Geometry"
- }
- };
+ return new OpenApiSchemaReference("Edm.Geometry", document);
}
///
/// Create for Edm.GeographyPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyPointSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyPointSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPoint"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryPoint", document);
}
///
/// Create for Edm.GeographyLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyLineStringSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyLineStringSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryLineString"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryLineString", document);
}
///
/// Create for Edm.GeographyPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyPolygonSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyPolygonSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryPolygon"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryPolygon", document);
}
///
/// Create for Edm.GeographyMultiPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiPointSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyMultiPointSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPoint"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiPoint", document);
}
///
/// Create for Edm.GeographyMultiLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiLineStringSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyMultiLineStringSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiLineString"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiLineString", document);
}
///
/// Create for Edm.GeographyMultiPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyMultiPolygonSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyMultiPolygonSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryMultiPolygon"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryMultiPolygon", document);
}
///
/// Create for Edm.GeographyCollection.
///
/// The created .
- public static OpenApiSchema CreateEdmGeographyCollectionSchema()
+ /// The document to use to lookup references.
+ public static IOpenApiSchema CreateEdmGeographyCollectionSchema(OpenApiDocument document)
{
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Edm.GeometryCollection"
- }
- };
+ return new OpenApiSchemaReference("Edm.GeometryCollection", document);
}
///
/// Create for Edm.Geometry.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometrySchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometrySchema(OpenApiDocument document)
{
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", document),
+ new OpenApiSchemaReference("Edm.GeometryLineString", document),
+ new OpenApiSchemaReference("Edm.GeometryPolygon", document),
+ new OpenApiSchemaReference("Edm.GeometryMultiPoint", document),
+ new OpenApiSchemaReference("Edm.GeometryMultiLineString", document),
+ new OpenApiSchemaReference("Edm.GeometryMultiPolygon", document),
+ new OpenApiSchemaReference("Edm.GeometryCollection", document),
+ ]
};
}
@@ -231,24 +179,25 @@ public static OpenApiSchema CreateEdmGeometrySchema()
/// Create for Edm.GeometryPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryPointSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryPointSchema(OpenApiDocument document)
{
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", document) }
},
Required = new HashSet
{
@@ -262,25 +211,26 @@ public static OpenApiSchema CreateEdmGeometryPointSchema()
/// Create for Edm.GeometryLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryLineStringSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryLineStringSchema(OpenApiDocument document)
{
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", document),
MinItems = 2
}
}
@@ -297,28 +247,29 @@ public static OpenApiSchema CreateEdmGeometryLineStringSchema()
/// Create for Edm.GeometryPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryPolygonSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryPolygonSchema(OpenApiDocument document)
{
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", document)
},
MinItems = 4
}
@@ -336,25 +287,26 @@ public static OpenApiSchema CreateEdmGeometryPolygonSchema()
/// Create for Edm.GeometryMultiPoint.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryMultiPointSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryMultiPointSchema(OpenApiDocument document)
{
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", document)
}
}
},
@@ -370,28 +322,29 @@ public static OpenApiSchema CreateEdmGeometryMultiPointSchema()
/// Create for Edm.GeometryMultiLineString.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryMultiLineStringSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryMultiLineStringSchema(OpenApiDocument document)
{
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", document)
},
MinItems = 2
}
@@ -409,31 +362,32 @@ public static OpenApiSchema CreateEdmGeometryMultiLineStringSchema()
/// Create for Edm.GeometryMultiPolygon.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryMultiPolygonSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryMultiPolygonSchema(OpenApiDocument document)
{
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", document)
}
},
MinItems = 4
@@ -452,25 +406,26 @@ public static OpenApiSchema CreateEdmGeometryMultiPolygonSchema()
/// Create for Edm.GeometryCollection.
///
/// The created .
- public static OpenApiSchema CreateEdmGeometryCollectionSchema()
+ /// The document to use to lookup references.
+ public static OpenApiSchema CreateEdmGeometryCollectionSchema(OpenApiDocument document)
{
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", document)
}
}
},
@@ -490,8 +445,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 373e14856..4f41a1e29 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
+++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj
@@ -29,7 +29,11 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
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..e42fdcdac 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
@@ -14,26 +14,26 @@ internal static class ODataConstants
///
/// Namespaces used in standard included models.
///
- public static IList StandardNamespaces = new List
- {
+ public readonly static List StandardNamespaces =
+ [
"Org.OData.",
"Edm",
"OData.Community.",
- };
+ ];
///
/// @odata.nextLink KeyValue pair
///
- public static KeyValuePair OdataNextLink = new("@odata.nextLink", new OpenApiSchema { Type = Constants.StringType, Nullable = true });
+ public readonly 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 readonly 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 readonly 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/ComplexPropertyBaseOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyBaseOperationHandler.cs
index 426386b2b..c23ab894f 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;
@@ -13,6 +14,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal abstract class ComplexPropertyBaseOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected ComplexPropertyBaseOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
protected ODataComplexPropertySegment ComplexPropertySegment;
///
@@ -29,15 +38,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, _document));
}
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..b8e01cccd 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;
@@ -17,6 +19,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal class ComplexPropertyGetOperationHandler : ComplexPropertyBaseOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public ComplexPropertyGetOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -54,7 +64,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,
@@ -62,35 +72,35 @@ protected override void SetParameters(OpenApiOperation operation)
// Capabilities.TopSupported, Capabilities.SkipSupported, Capabilities.SearchRestrictions,
// Capabilities.FilterRestrictions, and Capabilities.CountRestrictions
// $top
- parameter = Context.CreateTop(TargetPath) ?? Context.CreateTop(ComplexPropertySegment.Property);
+ parameter = Context.CreateTop(TargetPath, _document) ?? Context.CreateTop(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $skip
- parameter = Context.CreateSkip(TargetPath) ?? Context.CreateSkip(ComplexPropertySegment.Property);
+ parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $search
- parameter = Context.CreateSearch(TargetPath) ?? Context.CreateSearch(ComplexPropertySegment.Property);
+ parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $filter
- parameter = Context.CreateFilter(TargetPath) ?? Context.CreateFilter(ComplexPropertySegment.Property);
+ parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $count
- parameter = Context.CreateCount(TargetPath) ?? Context.CreateCount(ComplexPropertySegment.Property);
+ parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(ComplexPropertySegment.Property, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -130,12 +140,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,20 +159,12 @@ 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(), _document);
SetSingleResponse(operation, schema);
}
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -173,7 +175,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPatchOperationHandler.cs
index b95cd1c4e..43aeafa43 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPatchOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPatchOperationHandler.cs
@@ -9,6 +9,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal class ComplexPropertyPatchOperationHandler : ComplexPropertyUpdateOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public ComplexPropertyPatchOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Patch;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPostOperationHandler.cs
index 6fd736c64..1d6c4e93a 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;
@@ -17,6 +18,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal class ComplexPropertyPostOperationHandler : ComplexPropertyBaseOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public ComplexPropertyPostOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
protected override void Initialize(ODataContext context, ODataPath path)
{
@@ -65,7 +74,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
@@ -92,7 +101,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema());
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
@@ -103,7 +112,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -128,16 +137,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(), _document)
};
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPutOperationHandler.cs
index 83241ca74..3ea9d2995 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyPutOperationHandler.cs
@@ -9,6 +9,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal class ComplexPropertyPutOperationHandler : ComplexPropertyUpdateOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public ComplexPropertyPutOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Put;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/ComplexPropertyUpdateOperationHandler.cs
index cb9e616f1..c05aa00d3 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,6 +18,14 @@ namespace Microsoft.OpenApi.OData.Operation;
internal abstract class ComplexPropertyUpdateOperationHandler : ComplexPropertyBaseOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected ComplexPropertyUpdateOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
private UpdateRestrictionsType _updateRestrictions;
@@ -23,9 +33,9 @@ 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 +49,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);
}
@@ -69,7 +79,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema());
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
protected override void SetSecurity(OpenApiOperation operation)
@@ -79,7 +89,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -100,39 +110,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(), _document);
+
+ 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..226f45015 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;
@@ -20,6 +24,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class DollarCountGetOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public DollarCountGetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -31,7 +43,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 +51,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)
{
- annotatable = sourceSegment.NavigationSource as IEdmEntitySet;
+ annotatables.Add(sourceSegment.NavigationSource as IEdmEntitySet);
}
- else if (SecondLastSegment is ODataNavigationPropertySegment navigationPropertySegment)
+ else if (oDataSegment is ODataNavigationPropertySegment navigationPropertySegment)
{
- annotatable = navigationPropertySegment.NavigationProperty;
+ annotatables.Add(navigationPropertySegment.NavigationProperty);
+ }
+ else if (oDataSegment is ODataTypeCastSegment odataTypeCastSegment)
+ {
+ 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 +94,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 +111,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, _document));
}
string TagNameFromNavigationSourceSegment(ODataNavigationSourceSegment sourceSegment)
@@ -152,17 +171,10 @@ 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, _document)
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -172,20 +184,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, _document) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateSearch(x, _document)).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, _document) ?? (annotatables.Count == 0 ? null : annotatables.Select(x => Context.CreateFilter(x, _document)).FirstOrDefault(static x => x is not null));
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -194,15 +201,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..7d932f7e5 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmActionImportOperationHandler.cs
@@ -16,6 +16,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EdmActionImportOperationHandler : EdmOperationImportOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EdmActionImportOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Post;
@@ -25,7 +33,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
// The requestBody field contains a Request Body Object describing the structure of the request body.
// Its schema value follows the rules for Schema Objects for complex types, with one property per action parameter.
- operation.RequestBody = Context.CreateRequestBody(actionImport);
+ operation.RequestBody = Context.CreateRequestBody(actionImport, _document);
base.SetRequestBody(operation);
}
@@ -33,7 +41,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..39549df1f 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;
@@ -18,6 +19,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EdmActionOperationHandler : EdmOperationOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EdmActionOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Post;
@@ -41,19 +50,11 @@ protected override void SetBasicInfo(OpenApiOperation operation)
///
protected override void SetRequestBody(OpenApiOperation operation)
{
- if (EdmOperation is IEdmAction action && Context.CreateRequestBody(action) is OpenApiRequestBody requestBody)
+ if (EdmOperation is IEdmAction action && Context.CreateRequestBody(action, _document) is OpenApiRequestBody requestBody)
{
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", _document);
}
else
{
@@ -67,7 +68,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..94522cb92 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionImportOperationHandler.cs
@@ -16,6 +16,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EdmFunctionImportOperationHandler : EdmOperationImportOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EdmFunctionImportOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -24,11 +32,14 @@ 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)
{
- foreach (var param in Context.CreateParameters(functionImport.Function, OperationImportSegment.ParameterMappings))
+ foreach (var param in Context.CreateParameters(functionImport.Function, _document, OperationImportSegment.ParameterMappings))
{
operation.Parameters.AppendParameter(param);
}
@@ -37,7 +48,7 @@ protected override void SetParameters(OpenApiOperation operation)
{
//The parameters array contains a Parameter Object for each parameter of the function overload,
// and it contains specific Parameter Objects for the allowed system query options.
- foreach (var param in Context.CreateParameters(functionImport))
+ foreach (var param in Context.CreateParameters(functionImport, _document))
{
operation.Parameters.AppendParameter(param);
}
@@ -47,7 +58,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..559663ebf 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmFunctionOperationHandler.cs
@@ -17,6 +17,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EdmFunctionOperationHandler : EdmOperationOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EdmFunctionOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -45,7 +53,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..532c38e26 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;
@@ -22,6 +23,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class EdmOperationImportOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected EdmOperationImportOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
private OperationRestrictionsType _operationRestriction;
///
@@ -91,7 +100,7 @@ protected override void SetResponses(OpenApiOperation operation)
// describing the structure of the success response by referencing an appropriate schema
// in the global schemas. In addition, it contains a default name/value pair for
// the OData error response referencing the global responses.
- operation.Responses = Context.CreateResponses(EdmOperationImport);
+ operation.Responses = Context.CreateResponses(EdmOperationImport, _document);
base.SetResponses(operation);
}
@@ -104,7 +113,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
}
///
@@ -129,35 +138,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, _document));
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..cc2148507 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;
@@ -21,6 +23,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class EdmOperationOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The document to use to lookup references.
+ protected EdmOperationOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
private OperationRestrictionsType _operationRestriction;
///
@@ -143,8 +153,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, _document));
Context.AppendTag(tag);
@@ -200,7 +210,7 @@ protected override void SetParameters(OpenApiOperation operation)
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.Responses = Context.CreateResponses(EdmOperation);
+ operation.Responses = Context.CreateResponses(EdmOperation, _document);
base.SetResponses(operation);
}
@@ -212,7 +222,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_operationRestriction.Permissions, _document).ToList();
}
///
@@ -239,31 +249,31 @@ private void AppendSystemQueryOptions(IEdmFunction function, OpenApiOperation op
if (function.ReturnType.IsCollection())
{
// $top
- if (Context.CreateTop(function) is OpenApiParameter topParameter)
+ if (Context.CreateTop(function, _document) is {} topParameter)
{
operation.Parameters.AppendParameter(topParameter);
}
// $skip
- if (Context.CreateSkip(function) is OpenApiParameter skipParameter)
+ if (Context.CreateSkip(function, _document) is {} skipParameter)
{
operation.Parameters.AppendParameter(skipParameter);
}
// $search
- if (Context.CreateSearch(function) is OpenApiParameter searchParameter)
+ if (Context.CreateSearch(function, _document) is {} searchParameter)
{
operation.Parameters.AppendParameter(searchParameter);
}
// $filter
- if (Context.CreateFilter(function) is OpenApiParameter filterParameter)
+ if (Context.CreateFilter(function, _document) is {} filterParameter)
{
operation.Parameters.AppendParameter(filterParameter);
}
// $count
- if (Context.CreateCount(function) is OpenApiParameter countParameter)
+ if (Context.CreateCount(function, _document) is {} countParameter)
{
operation.Parameters.AppendParameter(countParameter);
}
@@ -271,19 +281,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 +336,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..343e8f997 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs
@@ -20,6 +20,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntityDeleteOperationHandler : EntitySetOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntityDeleteOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Delete;
@@ -76,7 +84,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
@@ -88,7 +96,7 @@ protected override void SetResponses(OpenApiOperation operation)
OpenApiConvertSettings settings = Context.Settings.Clone();
settings.UseSuccessStatusCodeRange = false;
- operation.AddErrorResponses(settings, true);
+ operation.AddErrorResponses(settings, _document, true);
base.SetResponses(operation);
}
@@ -99,7 +107,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs
index 8a506cf82..eca54745d 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
{
@@ -21,6 +23,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntityGetOperationHandler : EntitySetOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntityGetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -88,12 +98,12 @@ 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)
{
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model);
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document);
}
if (Context.Settings.ShowLinks)
@@ -104,15 +114,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(), _document);
}
operation.Responses = new OpenApiResponses
@@ -136,7 +138,7 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -159,7 +161,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs
index 1110a5ad0..b99f6d559 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs
@@ -14,6 +14,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntityPatchOperationHandler : EntityUpdateOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntityPatchOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Patch;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPutOperationHandler.cs
index aaf1b085f..7cb79f953 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPutOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPutOperationHandler.cs
@@ -14,6 +14,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntityPutOperationHandler : EntityUpdateOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntityPutOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Put;
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs
index 96b967d38..e4d4067c4 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;
@@ -22,6 +24,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntitySetGetOperationHandler : EntitySetOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntitySetGetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -57,12 +67,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,35 +88,35 @@ 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, _document) ?? Context.CreateTop(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $skip
- parameter = Context.CreateSkip(TargetPath) ?? Context.CreateSkip(EntitySet);
+ parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $search
- parameter = Context.CreateSearch(TargetPath) ?? Context.CreateSearch(EntitySet);
+ parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $filter
- parameter = Context.CreateFilter(TargetPath) ?? Context.CreateFilter(EntitySet);
+ parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
// $count
- parameter = Context.CreateCount(TargetPath) ?? Context.CreateCount(EntitySet);
+ parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(EntitySet, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -145,19 +155,11 @@ 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}", _document)
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -169,7 +171,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_readRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs
index 58c3f66d9..fb8bb6d28 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;
@@ -17,6 +18,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class EntitySetOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected EntitySetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
/// Gets/sets the .
///
@@ -36,16 +45,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, _document));
- Context.AppendTag(tag);
+ Context.AddExtensionToTag(tagName, Constants.xMsTocType, new OpenApiAny("page"), () => new OpenApiTag()
+ {
+ Name = tagName
+ });
base.SetTags(operation);
}
@@ -53,7 +60,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..4167d7d3b 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;
@@ -22,6 +24,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class EntitySetPostOperationHandler : EntitySetOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public EntitySetPostOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Post;
@@ -83,7 +93,7 @@ protected override void SetResponses(OpenApiOperation operation)
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -95,7 +105,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_insertRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -122,7 +132,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 +154,7 @@ private IDictionary GetContentDescription()
{
Schema = new OpenApiSchema
{
- Type = "string",
+ Type = JsonSchemaType.String,
Format = "binary"
}
});
@@ -181,29 +191,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, _document) :
+ new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityUpdateOperationHandler.cs
index 3595b30b7..01568a1b0 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;
@@ -19,6 +21,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class EntityUpdateOperationHandler : EntitySetOperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected EntityUpdateOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
private UpdateRestrictionsType _updateRestrictions;
protected override void Initialize(ODataContext context, ODataPath path)
@@ -76,7 +86,7 @@ protected override void SetRequestBody(OpenApiOperation operation)
protected IDictionary GetContent()
{
- OpenApiSchema schema = GetOpenApiSchema();
+ var schema = GetOpenApiSchema();
var content = new Dictionary();
IEnumerable mediaTypes = _updateRestrictions?.RequestContentTypes;
@@ -106,7 +116,7 @@ protected IDictionary GetContent()
///
protected override void SetResponses(OpenApiOperation operation)
{
- operation.AddErrorResponses(Context.Settings, true, GetOpenApiSchema());
+ operation.AddErrorResponses(Context.Settings, _document, true, GetOpenApiSchema());
base.SetResponses(operation);
}
@@ -117,7 +127,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_updateRestrictions.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
@@ -138,22 +148,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 EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType, Context.Model, _document);
}
- return new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = EntitySet.EntityType.FullName()
- }
- };
+ return new OpenApiSchemaReference(EntitySet.EntityType.FullName(), _document);
}
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
index ed65dbe27..0c311836c 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/IOperationHandlerProvider.cs
@@ -18,7 +18,8 @@ internal interface IOperationHandlerProvider
///
/// The path kind.
/// The operation type.
+ /// The Open API document to use to lookup references.
/// The corresponding .
- IOperationHandler GetHandler(ODataPathKind pathKind, OperationType operationType);
+ IOperationHandler GetHandler(ODataPathKind pathKind, OperationType operationType, OpenApiDocument document);
}
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
index 54e712a2c..fc71789a9 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityDeleteOperationHandler.cs
@@ -10,6 +10,14 @@ namespace Microsoft.OpenApi.OData.Operation
{
internal class MediaEntityDeleteOperationHandler : MediaEntityOperationalHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public MediaEntityDeleteOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Delete;
@@ -73,7 +81,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
@@ -85,7 +93,7 @@ protected override void SetResponses(OpenApiOperation operation)
OpenApiConvertSettings settings = Context.Settings.Clone();
settings.UseSuccessStatusCodeRange = false;
- operation.AddErrorResponses(settings, true);
+ operation.AddErrorResponses(settings, _document, true);
base.SetResponses(operation);
}
@@ -96,7 +104,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_deleteRestrictions.Permissions, _document).ToList();
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
index 125141e98..60a95ccdc 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs
@@ -19,31 +19,39 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class MediaEntityGetOperationHandler : MediaEntityOperationalHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public MediaEntityGetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
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 +59,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 +75,8 @@ protected override void SetBasicInfo(OpenApiOperation operation)
?? Context.Model.GetDescriptionAnnotation(Property);
}
else
- {
- // Structural property
+ {
+ // Structural property
description = _readRestrictions?.LongDescription ?? Context.Model.GetDescriptionAnnotation(Property);
}
@@ -96,7 +104,7 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -122,7 +130,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs
index 3a159ace6..422c22564 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;
@@ -19,6 +20,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class MediaEntityOperationalHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected MediaEntityOperationalHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
/// Gets/Sets the NavigationSource segment
///
@@ -56,7 +65,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 +91,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, _document));
}
///
@@ -112,7 +116,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 +150,7 @@ protected string GetOperationId(string prefix, string identifier)
}
}
- return string.Join(".", items);
+ return $"{string.Join(".", items)}-{Path.GetPathHash(Context.Settings)}";
}
///
@@ -166,7 +170,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..a1b9649ab 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;
@@ -20,6 +21,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class MediaEntityPutOperationHandler : MediaEntityOperationalHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public MediaEntityPutOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Put;
@@ -29,23 +38,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,21 +99,13 @@ 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()
- }
- };
-
- operation.AddErrorResponses(Context.Settings, addNoContent: true, schema: schema);
+ var schema = new OpenApiSchemaReference(entityType.FullName(), _document);
+
+ operation.AddErrorResponses(Context.Settings, _document, addNoContent: true, schema: schema);
}
else
{
- operation.AddErrorResponses(Context.Settings, true);
+ operation.AddErrorResponses(Context.Settings, _document, true);
}
base.SetResponses(operation);
@@ -120,7 +121,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(update.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(update.Permissions, _document).ToList();
}
///
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MetadataGetOperationHandler.cs
index f12e9fa98..9cba74f5d 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
{
@@ -15,6 +14,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class MetadataGetOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ public MetadataGetOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -46,7 +53,7 @@ protected override void SetResponses(OpenApiOperation operation)
{
OpenApiSchema schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
};
operation.Responses = new OpenApiResponses
@@ -69,7 +76,7 @@ protected override void SetResponses(OpenApiOperation operation)
}
}
};
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
index 11e852053..864c02ca8 100644
--- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
+++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyDeleteOperationHandler.cs
@@ -19,6 +19,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class NavigationPropertyDeleteOperationHandler : NavigationPropertyOperationHandler
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The document to use to lookups references.
+ public NavigationPropertyDeleteOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Delete;
@@ -61,7 +69,7 @@ protected override void SetParameters(OpenApiOperation operation)
Description = "ETag",
Schema = new OpenApiSchema
{
- Type = "string"
+ Type = JsonSchemaType.String
}
});
}
@@ -74,7 +82,7 @@ protected override void SetSecurity(OpenApiOperation operation)
return;
}
- operation.Security = Context.CreateSecurityRequirements(_deleteRestriction.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(_deleteRestriction.Permissions, _document).ToList();
}
///
@@ -84,7 +92,7 @@ protected override void SetResponses(OpenApiOperation operation)
OpenApiConvertSettings settings = Context.Settings.Clone();
settings.UseSuccessStatusCodeRange = false;
- operation.AddErrorResponses(settings, true);
+ operation.AddErrorResponses(settings, _document, true);
base.SetResponses(operation);
}
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyGetOperationHandler.cs
index fd94a4f50..6ca66c765 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;
@@ -22,6 +25,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal class NavigationPropertyGetOperationHandler : NavigationPropertyOperationHandler
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The document to use to lookup references.
+ public NavigationPropertyGetOperationHandler(OpenApiDocument document) : base(document)
+ {
+
+ }
///
public override OperationType OperationType => OperationType.Get;
@@ -64,13 +75,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 +91,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,41 +107,21 @@ 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}", _document)
}
};
}
else
{
- OpenApiSchema schema = null;
+ IOpenApiSchema schema = null;
var entityType = NavigationProperty.ToEntityType();
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
{
- schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, Context.Model);
+ schema = EdmModelHelper.GetDerivedTypesReferenceSchema(entityType, Context.Model, _document);
}
- if (schema == null)
- {
- schema = new OpenApiSchema
- {
- UnresolvedReference = true,
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = entityType.FullName()
- }
- };
- }
+ schema ??= new OpenApiSchemaReference(entityType.FullName(), _document);
operation.Responses = new OpenApiResponses
{
@@ -155,7 +146,7 @@ protected override void SetResponses(OpenApiOperation operation)
};
}
- operation.AddErrorResponses(Context.Settings, false);
+ operation.AddErrorResponses(Context.Settings, _document, false);
base.SetResponses(operation);
}
@@ -175,31 +166,31 @@ 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, _document) ?? Context.CreateTop(NavigationProperty, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateSkip(TargetPath) ?? Context.CreateSkip(NavigationProperty);
+ parameter = Context.CreateSkip(TargetPath, _document) ?? Context.CreateSkip(NavigationProperty, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateSearch(TargetPath) ?? Context.CreateSearch(NavigationProperty);
+ parameter = Context.CreateSearch(TargetPath, _document) ?? Context.CreateSearch(NavigationProperty, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateFilter(TargetPath) ?? Context.CreateFilter(NavigationProperty);
+ parameter = Context.CreateFilter(TargetPath, _document) ?? Context.CreateFilter(NavigationProperty, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
}
- parameter = Context.CreateCount(TargetPath) ?? Context.CreateCount(NavigationProperty);
+ parameter = Context.CreateCount(TargetPath, _document) ?? Context.CreateCount(NavigationProperty, _document);
if (parameter != null)
{
operation.Parameters.Add(parameter);
@@ -248,7 +239,7 @@ protected override void SetSecurity(OpenApiOperation operation)
readBase = _readRestriction.ReadByKeyRestrictions;
}
- operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList();
+ operation.Security = Context.CreateSecurityRequirements(readBase.Permissions, _document).ToList();
}
protected override void AppendCustomParameters(OpenApiOperation operation)
diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs
index 743a10e88..240a6e2bd 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;
@@ -21,6 +23,14 @@ namespace Microsoft.OpenApi.OData.Operation
///
internal abstract class NavigationPropertyOperationHandler : OperationHandler
{
+ ///
+ /// Initializes a new instance of class.
+ ///
+ /// The document to use to lookup references.
+ protected NavigationPropertyOperationHandler(OpenApiDocument document):base(document)
+ {
+
+ }
///
/// Gets the navigation property.
///
@@ -39,10 +49,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 +70,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 +95,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, _document));
base.SetTags(operation);
}
@@ -100,7 +107,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 +123,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