From c1e41a97904b83fc52296dd2f9bd2068f4d04a4e Mon Sep 17 00:00:00 2001 From: Irvine Sunday Date: Wed, 22 Jul 2020 11:40:39 +0300 Subject: [PATCH 01/12] Bump up Microsoft.OpenAPI lib. version --- .../Microsoft.OpenAPI.OData.Reader.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0238ea28..a62e1489 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj +++ b/src/Microsoft.OpenApi.OData.Reader/Microsoft.OpenAPI.OData.Reader.csproj @@ -20,7 +20,7 @@ - + From bcd2631d29a1c6789cea422535b1a4297e510137 Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Thu, 23 Jul 2020 15:38:08 +0300 Subject: [PATCH 02/12] Adds in updates to the root path generation feature (#2) * Update root path settings * Add back option to generate root path Co-authored-by: Irvine Sunday --- .../Generator/OpenApiPathItemGenerator.cs | 34 +++++++++++++++++++ .../OpenApiConvertSettings.cs | 8 ++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs index 8c834ec4..253a4ccc 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiPathItemGenerator.cs @@ -4,6 +4,7 @@ // ------------------------------------------------------------ using System.Collections.Generic; +using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; @@ -44,7 +45,40 @@ public static IDictionary CreatePathItems(this ODataCon pathItems.Add(path.GetPathItemName(settings), handler.CreatePathItem(context, path)); } + if (settings.ShowRootPath) + { + OpenApiPathItem rootPath = new OpenApiPathItem() + { + Operations = new Dictionary { + { + OperationType.Get, new OpenApiOperation { + OperationId = "graphService.GetGraphService", + Responses = new OpenApiResponses() + { + { "200",new OpenApiResponse() { + Description = "OK", + Links = CreateRootLinks(context.EntityContainer) + } + } + } + } + } + } + }; + pathItems.Add("/", rootPath); + } + return pathItems; } + + private static IDictionary CreateRootLinks(IEdmEntityContainer entityContainer) + { + var links = new Dictionary(); + foreach (var element in entityContainer.Elements) + { + links.Add(element.Name, new OpenApiLink()); + } + return links; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs index b7c2c4b0..8cfd5112 100644 --- a/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OpenApiConvertSettings.cs @@ -130,6 +130,11 @@ public class OpenApiConvertSettings /// public bool ShowSchemaExamples { get; set; } = false; + /// + /// Gets/sets a value indicating whether or not to show the root path of the described API. + /// + public bool ShowRootPath { get; set; } = false; + internal OpenApiConvertSettings Clone() { var newSettings = new OpenApiConvertSettings @@ -156,7 +161,8 @@ internal OpenApiConvertSettings Clone() EnableDerivedTypesReferencesForRequestBody = this.EnableDerivedTypesReferencesForRequestBody, PathPrefix = this.PathPrefix, ShowLinks = this.ShowLinks, - ShowSchemaExamples = this.ShowSchemaExamples + ShowSchemaExamples = this.ShowSchemaExamples, + ShowRootPath = this.ShowRootPath }; return newSettings; From 135b6f5131e06e647904e02313bf439c9f531e2d Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Fri, 24 Jul 2020 23:50:02 +0300 Subject: [PATCH 03/12] Fixes generating of OpenAPI doc. when PrefixEntityTypeNameBeforeKey is enabled (#3) * Update to version 1.0.4 * Remove setting of the keyName for setting PrefixEntityTypeNameBeforeKey All the dictionary `parameterNameMapping` keys are set with the default parameter keys. * Add back prefixEntityTypeNameBeforeKey check and add parameterNameMapping check * Bump up lib versions Co-authored-by: Sam Xu Co-authored-by: Irvine Sunday --- .../Generator/OpenApiParameterGenerator.cs | 7 +++++-- src/OoasGui/OoasGui.csproj | 4 ++-- src/OoasGui/packages.config | 2 +- .../Microsoft.OpenAPI.OData.Reader.Tests.csproj | 2 +- tool/versioning.props | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs index 8c19d76d..533098a2 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs @@ -30,7 +30,7 @@ internal static class OpenApiParameterGenerator public static IDictionary CreateParameters(this ODataContext context) { Utils.CheckArgumentNull(context, nameof(context)); - + // 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 @@ -134,7 +134,10 @@ public static IList CreateKeyParameters(this ODataContext cont if (keys.Count() == 1) { string keyName = keys.First().Name; - if (context.Settings.PrefixEntityTypeNameBeforeKey) + + // If dictionary parameterNameMapping is defined, there's no need of setting the + // keyName, we will retrieve this from the dictionary key. + if (context.Settings.PrefixEntityTypeNameBeforeKey && parameterNameMapping == null) { keyName = entityType.Name + "-" + keys.First().Name; } diff --git a/src/OoasGui/OoasGui.csproj b/src/OoasGui/OoasGui.csproj index be7423f9..b1db143b 100644 --- a/src/OoasGui/OoasGui.csproj +++ b/src/OoasGui/OoasGui.csproj @@ -35,8 +35,8 @@ ..\..\packages\Microsoft.OData.Edm.7.6.1\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll - - ..\..\packages\Microsoft.OpenApi.1.1.4\lib\net46\Microsoft.OpenApi.dll + + ..\..\packages\Microsoft.OpenApi.1.2.2\lib\net46\Microsoft.OpenApi.dll diff --git a/src/OoasGui/packages.config b/src/OoasGui/packages.config index 5c396329..89e60b5b 100644 --- a/src/OoasGui/packages.config +++ b/src/OoasGui/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj b/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj index a9b3b4be..d24893f3 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Microsoft.OpenAPI.OData.Reader.Tests.csproj @@ -62,7 +62,7 @@ - + all diff --git a/tool/versioning.props b/tool/versioning.props index e8218a2c..22fc8ba8 100644 --- a/tool/versioning.props +++ b/tool/versioning.props @@ -14,7 +14,7 @@ 1 0 - 3 + 4 From 06b12430cdff241183c6e64237a388c4e8c24411 Mon Sep 17 00:00:00 2001 From: Irvine Sunday Date: Mon, 3 Aug 2020 13:23:19 +0300 Subject: [PATCH 04/12] Update Microsoft.OpenAPI lib version --- tool/UpdateDocs/UpdateDocs.csproj | 4 ++-- tool/UpdateDocs/packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tool/UpdateDocs/UpdateDocs.csproj b/tool/UpdateDocs/UpdateDocs.csproj index a6fdfc75..809b34e9 100644 --- a/tool/UpdateDocs/UpdateDocs.csproj +++ b/tool/UpdateDocs/UpdateDocs.csproj @@ -35,8 +35,8 @@ packages\Microsoft.OData.Edm.7.6.1\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll - - packages\Microsoft.OpenApi.1.1.4\lib\net46\Microsoft.OpenApi.dll + + packages\Microsoft.OpenApi.1.2.2\lib\net46\Microsoft.OpenApi.dll diff --git a/tool/UpdateDocs/packages.config b/tool/UpdateDocs/packages.config index 5c396329..e224131c 100644 --- a/tool/UpdateDocs/packages.config +++ b/tool/UpdateDocs/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file From 8db6488706858b82e8d17f65696ae95189451bfa Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Tue, 11 Aug 2020 22:27:45 +0300 Subject: [PATCH 05/12] Fix: Update /$ref update operation from PATCH to PUT (#4) * Switch $ref operation from PATCH to PUT See: http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793759 * Typo fix * Update tests and test class names appropriately * Update test resource files appropriately * Change schema type from 'String' to 'object' * Delete operations are only valid for non-collection of navProps * Update ref test and test resource files * typo fix Co-authored-by: DeVere Dyett * Update test files with additionalProperties object * Add additionalProperties property to response schema Co-authored-by: Peter Ombwa * Update test files with additionalProperties object in response schema * Revert return type for response schema Co-authored-by: Peter Ombwa * Revert response schema type to object * Revert test files response schema; remove additionalProperties property Co-authored-by: Irvine Sunday Co-authored-by: DeVere Dyett Co-authored-by: Peter Ombwa --- .../Operation/OperationHandlerProvider.cs | 4 +- .../Operation/RefPostOperationHandler.cs | 5 +- ...onHandler.cs => RefPutOperationHandler.cs} | 5 +- .../PathItem/PathItemHandler.cs | 2 +- .../PathItem/RefPathItemHandler.cs | 14 +- .../OperationHandlerProviderTests.cs | 2 +- ...ests.cs => RefPutOperationHandlerTests.cs} | 8 +- .../PathItem/RefPathItemHandlerTests.cs | 4 +- .../Resources/Multiple.Schema.OpenApi.V2.json | 151 ++------- .../Resources/Multiple.Schema.OpenApi.V2.yaml | 111 +------ .../Resources/Multiple.Schema.OpenApi.json | 169 ++-------- .../Resources/Multiple.Schema.OpenApi.yaml | 120 +------ .../Resources/TripService.OpenApi.V2.json | 275 +++------------- .../Resources/TripService.OpenApi.V2.yaml | 198 ++--------- .../Resources/TripService.OpenApi.json | 307 +++--------------- .../Resources/TripService.OpenApi.yaml | 214 ++---------- 16 files changed, 256 insertions(+), 1333 deletions(-) rename src/Microsoft.OpenApi.OData.Reader/Operation/{RefPatchOperationHandler.cs => RefPutOperationHandler.cs} (94%) rename test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/{RefPatchOperationHandlerTests.cs => RefPutOperationHandlerTests.cs} (88%) diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs index 8679e01d..763f84a8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs @@ -68,11 +68,11 @@ public OperationHandlerProvider() {OperationType.Delete, new NavigationPropertyDeleteOperationHandler() } }; - // navigatoin property ref (Get/Post/Patch/Delete) + // navigation property ref (Get/Post/Put/Delete) _handlers[ODataPathKind.Ref] = new Dictionary { {OperationType.Get, new RefGetOperationHandler() }, - {OperationType.Patch, new RefPatchOperationHandler() }, + {OperationType.Put, new RefPutOperationHandler() }, {OperationType.Post, new RefPostOperationHandler() }, {OperationType.Delete, new RefDeleteOperationHandler() } }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs index 33226765..ede32705 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPostOperationHandler.cs @@ -40,7 +40,8 @@ protected override void SetRequestBody(OpenApiOperation operation) { OpenApiSchema schema = new OpenApiSchema { - Type = "String" + Type = "object", + AdditionalProperties = new OpenApiSchema { Type = "object" } }; operation.RequestBody = new OpenApiRequestBody @@ -66,7 +67,7 @@ protected override void SetResponses(OpenApiOperation operation) { OpenApiSchema schema = new OpenApiSchema { - Type = "String" // What to return? + Type = "object" }; operation.Responses = new OpenApiResponses diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs similarity index 94% rename from src/Microsoft.OpenApi.OData.Reader/Operation/RefPatchOperationHandler.cs rename to src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs index 74aa410e..0a97ca6f 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/RefPatchOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/RefPutOperationHandler.cs @@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.OData.Operation /// /// Update a navigation property ref for a navigation source. /// - internal class RefPatchOperationHandler : NavigationPropertyOperationHandler + internal class RefPutOperationHandler : NavigationPropertyOperationHandler { /// public override OperationType OperationType => OperationType.Patch; @@ -40,7 +40,8 @@ protected override void SetRequestBody(OpenApiOperation operation) { OpenApiSchema schema = new OpenApiSchema { - Type = "String" + Type = "object", + AdditionalProperties = new OpenApiSchema { Type = "object" } }; operation.RequestBody = new OpenApiRequestBody diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs index a65bd827..eff041bc 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs @@ -80,7 +80,7 @@ protected virtual void SetExtensions(OpenApiPathItem item) /// Add one operation into path item. /// /// The path item. - /// The operatin type. + /// The operation type. protected virtual void AddOperation(OpenApiPathItem item, OperationType operationType) { IOperationHandlerProvider provider = Context.OperationHanderProvider; diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/RefPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/RefPathItemHandler.cs index 64356621..60a18bf2 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/RefPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/RefPathItemHandler.cs @@ -90,15 +90,15 @@ protected override void SetOperations(OpenApiPathItem item) UpdateRestrictionsType update = restriction?.UpdateRestrictions; if (update == null || update.IsUpdatable) { - AddOperation(item, OperationType.Patch); + AddOperation(item, OperationType.Put); } - } - // delete the link - DeleteRestrictionsType delete = restriction?.DeleteRestrictions; - if (delete == null || delete.IsDeletable) - { - AddOperation(item, OperationType.Delete); + // delete the link + DeleteRestrictionsType delete = restriction?.DeleteRestrictions; + if (delete == null || delete.IsDeletable) + { + AddOperation(item, OperationType.Delete); + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs index 942cfdd7..ca6e588b 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs @@ -31,7 +31,7 @@ public class OperationHandlerProviderTests [InlineData(ODataPathKind.Ref, OperationType.Post, typeof(RefPostOperationHandler))] [InlineData(ODataPathKind.Ref, OperationType.Delete, typeof(RefDeleteOperationHandler))] [InlineData(ODataPathKind.Ref, OperationType.Get, typeof(RefGetOperationHandler))] - [InlineData(ODataPathKind.Ref, OperationType.Patch, typeof(RefPatchOperationHandler))] + [InlineData(ODataPathKind.Ref, OperationType.Put, typeof(RefPutOperationHandler))] public void GetHandlerReturnsCorrectOperationHandlerType(ODataPathKind pathKind, OperationType operationType, Type handlerType) { // Arrange diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs similarity index 88% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPatchOperationHandlerTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs index cacd40a0..f0333759 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/RefPutOperationHandlerTests.cs @@ -4,23 +4,21 @@ // ------------------------------------------------------------ using Microsoft.OData.Edm; -using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.OData.Edm; -using Microsoft.OpenApi.OData.PathItem.Tests; using Microsoft.OpenApi.OData.Tests; using System.Linq; using Xunit; namespace Microsoft.OpenApi.OData.Operation.Tests { - public class RefPatchOperationHandlerTests + public class RefPutOperationHandlerTests { - private RefPatchOperationHandler _operationHandler = new RefPatchOperationHandler(); + private RefPutOperationHandler _operationHandler = new RefPutOperationHandler(); [Theory] [InlineData(true)] [InlineData(false)] - public void CreateNavigationRefPatchOperationReturnsCorrectOperation(bool enableOperationId) + public void CreateNavigationRefPutOperationReturnsCorrectOperation(bool enableOperationId) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/RefPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/RefPathItemHandlerTests.cs index 30869c2a..ee055a43 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/RefPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/RefPathItemHandlerTests.cs @@ -57,8 +57,8 @@ public void CreatePathItemThrowsForNonNavigationPropertyPath() } [Theory] - [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Post, OperationType.Delete })] - [InlineData(false, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })] + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Post})] + [InlineData(false, new OperationType[] { OperationType.Get, OperationType.Put, OperationType.Delete })] public void CreateNavigationPropertyRefPathItemReturnsCorrectPathItem(bool collectionNav, OperationType[] expected) { // Arrange diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json index 0e8b96b8..0ce89148 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json @@ -998,7 +998,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -1006,7 +1009,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -1014,47 +1017,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Documents.RevisionDto" - ], - "summary": "Delete ref of navigation property Revisions for Documents", - "operationId": "Documents.DeleteRefRevisions", - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of DocumentDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Libraries": { @@ -1707,7 +1669,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -1715,7 +1680,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -1723,47 +1688,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Libraries.DocumentDto" - ], - "summary": "Delete ref of navigation property Documents for Libraries", - "operationId": "Libraries.DeleteRefDocuments", - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of LibraryDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "LibraryDto" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Revisions": { @@ -2245,7 +2169,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "Revisions.Document" ], @@ -2272,7 +2196,10 @@ "description": "New navigation property ref values", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -3031,7 +2958,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -3039,7 +2969,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -3047,47 +2977,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Tasks.RevisionDto" - ], - "summary": "Delete ref of navigation property Revisions for Tasks", - "operationId": "Tasks.DeleteRefRevisions", - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of DocumentDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } } }, diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml index 19f76f4d..0c6f7654 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml @@ -720,41 +720,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Documents.RevisionDto - summary: Delete ref of navigation property Revisions for Documents - operationId: Documents.DeleteRefRevisions - parameters: - - in: path - name: Id - description: 'key: Id of DocumentDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: DocumentDto - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -1231,41 +1204,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Libraries.DocumentDto - summary: Delete ref of navigation property Documents for Libraries - operationId: Libraries.DeleteRefDocuments - parameters: - - in: path - name: Id - description: 'key: Id of LibraryDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: LibraryDto - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -1632,7 +1578,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - Revisions.Document summary: Update the ref of navigation property Document in Revisions @@ -1654,7 +1600,9 @@ paths: description: New navigation property ref values required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '204': description: Success @@ -2207,41 +2155,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Tasks.RevisionDto - summary: Delete ref of navigation property Revisions for Tasks - operationId: Tasks.DeleteRefRevisions - parameters: - - in: path - name: Id - description: 'key: Id of DocumentDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: DocumentDto - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json index 2d9ce89a..055c92df 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json @@ -1120,7 +1120,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -1132,7 +1135,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -1142,53 +1145,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Documents.RevisionDto" - ], - "summary": "Delete ref of navigation property Revisions for Documents", - "operationId": "Documents.DeleteRefRevisions", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of DocumentDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Libraries": { @@ -1927,7 +1883,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -1939,7 +1898,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -1949,53 +1908,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Libraries.DocumentDto" - ], - "summary": "Delete ref of navigation property Documents for Libraries", - "operationId": "Libraries.DeleteRefDocuments", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of LibraryDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "LibraryDto" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Revisions": { @@ -2597,7 +2509,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "Revisions.Document" ], @@ -2623,7 +2535,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -3477,7 +3392,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -3489,7 +3407,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -3499,53 +3417,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Tasks.RevisionDto" - ], - "summary": "Delete ref of navigation property Revisions for Tasks", - "operationId": "Tasks.DeleteRefRevisions", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of DocumentDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } } }, diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml index 47d8e433..feeaf017 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml @@ -798,7 +798,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -806,39 +808,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Documents.RevisionDto - summary: Delete ref of navigation property Revisions for Documents - operationId: Documents.DeleteRefRevisions - parameters: - - name: Id - in: path - description: 'key: Id of DocumentDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: DocumentDto - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -1372,7 +1342,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -1380,39 +1352,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Libraries.DocumentDto - summary: Delete ref of navigation property Documents for Libraries - operationId: Libraries.DeleteRefDocuments - parameters: - - name: Id - in: path - description: 'key: Id of LibraryDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: LibraryDto - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -1857,7 +1797,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - Revisions.Document summary: Update the ref of navigation property Document in Revisions @@ -1878,7 +1818,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '204': @@ -2492,7 +2434,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -2500,39 +2444,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Tasks.RevisionDto - summary: Delete ref of navigation property Revisions for Tasks - operationId: Tasks.DeleteRefRevisions - parameters: - - name: Id - in: path - description: 'key: Id of DocumentDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: DocumentDto - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json index 711b8c74..c26fef34 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json @@ -774,7 +774,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "Me.Person" ], @@ -790,7 +790,10 @@ "description": "New navigation property ref values", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -1127,7 +1130,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -1135,7 +1141,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -1143,36 +1149,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Me.Person" - ], - "summary": "Delete ref of navigation property Friends for Me", - "operationId": "Me.DeleteRefFriends", - "parameters": [ - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -1677,7 +1653,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -1685,7 +1664,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -1693,36 +1672,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Me.Trip" - ], - "summary": "Delete ref of navigation property Trips for Me", - "operationId": "Me.DeleteRefTrips", - "parameters": [ - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/NewComePeople": { @@ -2134,7 +2083,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "NewComePeople.Person" ], @@ -2158,7 +2107,10 @@ "description": "New navigation property ref values", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -2535,7 +2487,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -2543,7 +2498,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -2551,44 +2506,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "NewComePeople.Person" - ], - "summary": "Delete ref of navigation property Friends for NewComePeople", - "operationId": "NewComePeople.DeleteRefFriends", - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -3175,7 +3092,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -3183,7 +3103,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -3191,44 +3111,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "NewComePeople.Trip" - ], - "summary": "Delete ref of navigation property Trips for NewComePeople", - "operationId": "NewComePeople.DeleteRefTrips", - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/People": { @@ -3640,7 +3522,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "People.Person" ], @@ -3664,7 +3546,10 @@ "description": "New navigation property ref values", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -4041,7 +3926,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -4049,7 +3937,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -4057,44 +3945,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "People.Person" - ], - "summary": "Delete ref of navigation property Friends for People", - "operationId": "People.DeleteRefFriends", - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -4681,7 +4531,10 @@ "description": "New navigation property ref value", "required": true, "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } ], @@ -4689,7 +4542,7 @@ "201": { "description": "Created navigation property link.", "schema": { - "type": "String" + "type": "object" } }, "default": { @@ -4697,44 +4550,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "People.Trip" - ], - "summary": "Delete ref of navigation property Trips for People", - "operationId": "People.DeleteRefTrips", - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "header", - "name": "If-Match", - "description": "ETag", - "type": "string" - }, - { - "in": "query", - "name": "@id", - "description": "Delete Uri", - "type": "string" - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/ResetDataSource": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml index 0cb2eff2..ef6a7284 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml @@ -525,7 +525,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - Me.Person summary: Update the ref of navigation property BestFriend in Me @@ -538,7 +538,9 @@ paths: description: New navigation property ref values required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '204': description: Success @@ -777,32 +779,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Me.Person - summary: Delete ref of navigation property Friends for Me - operationId: Me.DeleteRefFriends - parameters: - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -1152,32 +1136,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Me.Trip - summary: Delete ref of navigation property Trips for Me - operationId: Me.DeleteRefTrips - parameters: - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -1474,7 +1440,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - NewComePeople.Person summary: Update the ref of navigation property BestFriend in NewComePeople @@ -1493,7 +1459,9 @@ paths: description: New navigation property ref values required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '204': description: Success @@ -1762,38 +1730,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - NewComePeople.Person - summary: Delete ref of navigation property Friends for NewComePeople - operationId: NewComePeople.DeleteRefFriends - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -2204,38 +2148,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - NewComePeople.Trip - summary: Delete ref of navigation property Trips for NewComePeople - operationId: NewComePeople.DeleteRefTrips - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -2532,7 +2452,7 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - People.Person summary: Update the ref of navigation property BestFriend in People @@ -2551,7 +2471,9 @@ paths: description: New navigation property ref values required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '204': description: Success @@ -2820,38 +2742,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - People.Person - summary: Delete ref of navigation property Friends for People - operationId: People.DeleteRefFriends - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation @@ -3262,38 +3160,14 @@ paths: description: New navigation property ref value required: true schema: - type: String + type: object + additionalProperties: + type: object responses: '201': description: Created navigation property link. schema: - type: String - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - People.Trip - summary: Delete ref of navigation property Trips for People - operationId: People.DeleteRefTrips - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: header - name: If-Match - description: ETag - type: string - - in: query - name: '@id' - description: Delete Uri - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/responses/error' x-ms-docs-operation-type: operation diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json index 2d306233..4928e181 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json @@ -904,7 +904,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "Me.Person" ], @@ -915,7 +915,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -1283,7 +1286,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -1295,7 +1301,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -1305,40 +1311,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Me.Person" - ], - "summary": "Delete ref of navigation property Friends for Me", - "operationId": "Me.DeleteRefFriends", - "parameters": [ - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -1895,7 +1867,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -1907,7 +1882,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -1917,40 +1892,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "Me.Trip" - ], - "summary": "Delete ref of navigation property Trips for Me", - "operationId": "Me.DeleteRefTrips", - "parameters": [ - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/NewComePeople": { @@ -2410,7 +2351,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "NewComePeople.Person" ], @@ -2433,7 +2374,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -2853,7 +2797,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -2865,7 +2812,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -2875,50 +2822,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "NewComePeople.Person" - ], - "summary": "Delete ref of navigation property Friends for NewComePeople", - "operationId": "NewComePeople.DeleteRefFriends", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -3583,7 +3486,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -3595,7 +3501,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -3605,50 +3511,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "NewComePeople.Trip" - ], - "summary": "Delete ref of navigation property Trips for NewComePeople", - "operationId": "NewComePeople.DeleteRefTrips", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/People": { @@ -4108,7 +3970,7 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "put": { "tags": [ "People.Person" ], @@ -4131,7 +3993,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -4551,7 +4416,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -4563,7 +4431,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -4573,50 +4441,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "People.Person" - ], - "summary": "Delete ref of navigation property Friends for People", - "operationId": "People.DeleteRefFriends", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { @@ -5281,7 +5105,10 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, @@ -5293,7 +5120,7 @@ "content": { "application/json": { "schema": { - "type": "String" + "type": "object" } } } @@ -5303,50 +5130,6 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "People.Trip" - ], - "summary": "Delete ref of navigation property Trips for People", - "operationId": "People.DeleteRefTrips", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" - } - }, - { - "name": "@id", - "in": "query", - "description": "Delete Uri", - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" } }, "/ResetDataSource": { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml index ec59ccc8..4108eb61 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml @@ -599,7 +599,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - Me.Person summary: Update the ref of navigation property BestFriend in Me @@ -609,7 +609,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '204': @@ -870,7 +872,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -878,29 +882,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Me.Person - summary: Delete ref of navigation property Friends for Me - operationId: Me.DeleteRefFriends - parameters: - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -1277,7 +1259,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -1285,29 +1269,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - Me.Trip - summary: Delete ref of navigation property Trips for Me - operationId: Me.DeleteRefTrips - parameters: - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -1635,7 +1597,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - NewComePeople.Person summary: Update the ref of navigation property BestFriend in NewComePeople @@ -1653,7 +1615,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '204': @@ -1950,7 +1914,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -1958,36 +1924,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - NewComePeople.Person - summary: Delete ref of navigation property Friends for NewComePeople - operationId: NewComePeople.DeleteRefFriends - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -2438,7 +2375,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -2446,36 +2385,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - NewComePeople.Trip - summary: Delete ref of navigation property Trips for NewComePeople - operationId: NewComePeople.DeleteRefTrips - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -2803,7 +2713,7 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - patch: + put: tags: - People.Person summary: Update the ref of navigation property BestFriend in People @@ -2821,7 +2731,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '204': @@ -3118,7 +3030,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -3126,36 +3040,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - People.Person - summary: Delete ref of navigation property Friends for People - operationId: People.DeleteRefFriends - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -3606,7 +3491,9 @@ paths: content: application/json: schema: - type: String + type: object + additionalProperties: + type: object required: true responses: '201': @@ -3614,36 +3501,7 @@ paths: content: application/json: schema: - type: String - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - delete: - tags: - - People.Trip - summary: Delete ref of navigation property Trips for People - operationId: People.DeleteRefTrips - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: If-Match - in: header - description: ETag - schema: - type: string - - name: '@id' - in: query - description: Delete Uri - schema: - type: string - responses: - '204': - description: Success + type: object default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation From 496aa865a4e1d5351ed4780e9a7232238323400f Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Tue, 18 Aug 2020 18:46:00 +0300 Subject: [PATCH 06/12] Supports generation of stream paths (#5) * Add new constant - ApplicationOctetStream * Update Edm classes with new media entity path kind and new segment kinds * Add new OData segments StreamContent and StreamProperty segments for Media Entity PathKind * Add new Media Entity operations Get & Put * Update operation handler with new media entity operations Get & Put * Add new Media Entity path item handler * Update PathItemHandlerProvider with the new Media Entity path item handler MediaEntityPathItemHandler * Update Edm path tests to validate Media Entity paths * Add tests for StreamProperty & StreamContent OData segments * Add tests for Media Entity operation handlers Get & Put operational handlers * Update OperationHandlerProviderTest with new test fixture for Media Entity * Add tests for MediaEntityPathItemHandler * Update PathItemHandlerProviderTests with new test fixture for Media Entity Co-authored-by: Irvine Sunday --- .../Common/Constants.cs | 5 + .../Edm/ODataPath.cs | 6 +- .../Edm/ODataPathKind.cs | 9 +- .../Edm/ODataPathProvider.cs | 31 ++- .../Edm/ODataSegment.cs | 12 +- .../Edm/ODataStreamContentSegment.cs | 24 ++ .../Edm/ODataStreamPropertySegment.cs | 34 +++ .../MediaEntityGetOperationHandler.cs | 109 +++++++++ .../MediaEntityPutOperationHandler.cs | 104 +++++++++ .../Operation/OperationHandlerProvider.cs | 7 + .../PathItem/MediaEntityPathItemHandler.cs | 38 ++++ .../PathItem/PathItemHandlerProvider.cs | 3 + .../Edm/ODataPathProviderTests.cs | 76 ++++++- .../Edm/ODataPathTests.cs | 28 ++- .../Edm/ODataStreamContentSegmentTests.cs | 57 +++++ .../Edm/ODataStreamPropertySegmentTests.cs | 70 ++++++ .../MediaEntityGetOperationHandlerTests.cs | 89 ++++++++ .../MediaEntityPutOperationHandlerTests.cs | 63 ++++++ .../OperationHandlerProviderTests.cs | 2 + .../MediaEntityPathItemHandlerTests.cs | 206 ++++++++++++++++++ .../PathItem/PathItemHandlerProviderTests.cs | 1 + 21 files changed, 960 insertions(+), 14 deletions(-) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamContentSegmentTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamPropertySegmentTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs index 4df0d422..b33bec10 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Common/Constants.cs @@ -15,6 +15,11 @@ internal static class Constants /// public static string ApplicationJsonMediaType = "application/json"; + /// + /// application/octet-stream + /// + public static string ApplicationOctetStreamMediaType = "application/octet-stream"; + /// /// Status code: 200 /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs index bd5abab9..a052bfe9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPath.cs @@ -258,7 +258,11 @@ public int CompareTo(ODataPath other) private ODataPathKind CalcPathType() { - if (Segments.Any(c => c.Kind == ODataSegmentKind.Ref)) + if (Segments.Any(c => c.Kind == ODataSegmentKind.StreamProperty || c.Kind == ODataSegmentKind.StreamContent)) + { + return ODataPathKind.MediaEntity; + } + else if (Segments.Any(c => c.Kind == ODataSegmentKind.Ref)) { return ODataPathKind.Ref; } diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs index 2a412150..14498a00 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathKind.cs @@ -36,15 +36,20 @@ public enum ODataPathKind OperationImport, /// - /// Represents an navigation propert path, for example: ~/users/{id}/onedrive + /// Represents an navigation property path, for example: ~/users/{id}/onedrive /// NavigationProperty, /// - /// Represents an navigation propert $ref path, for example: ~/users/{id}/onedrive/$ref + /// Represents an navigation property $ref path, for example: ~/users/{id}/onedrive/$ref /// Ref, + /// + /// Represents a media entity path, for example: ~/me/photo/$value or ~/reports/deviceConfigurationUserActivity/Content + /// + MediaEntity, + /// /// Represents an un-supported/unknown path. /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs index 4273bb73..a6b877b9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs @@ -126,6 +126,7 @@ private void AppendPath(ODataPath path) case ODataPathKind.Entity: case ODataPathKind.EntitySet: case ODataPathKind.Singleton: + case ODataPathKind.MediaEntity: ODataNavigationSourceSegment navigationSourceSegment = (ODataNavigationSourceSegment)path.FirstSegment; if (!_allNavigationSourcePaths.TryGetValue(navigationSourceSegment.EntityType, out IList nsList)) { @@ -182,6 +183,33 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource AppendPath(path.Clone()); } + // media entity + bool createValuePath = true; + foreach (IEdmStructuralProperty sp in entityType.DeclaredStructuralProperties()) + { + if (sp.Type.AsPrimitive().IsStream()) + { + path.Push(new ODataStreamPropertySegment(sp.Name)); + AppendPath(path.Clone()); + path.Pop(); + } + + if (sp.Name.Equals("content", System.StringComparison.OrdinalIgnoreCase)) + { + createValuePath = false; + } + } + + /* Create a /$value path only if entity has stream and + * does not contain a structural property named Content + */ + if (createValuePath && entityType.HasStream) + { + path.Push(new ODataStreamContentSegment()); + AppendPath(path.Clone()); + path.Pop(); + } + // navigation property foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) { @@ -369,7 +397,8 @@ private bool AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperati foreach (var subPath in value) { if ((isCollection && subPath.Kind == ODataPathKind.EntitySet) || - (!isCollection && subPath.Kind != ODataPathKind.EntitySet)) + (!isCollection && subPath.Kind != ODataPathKind.EntitySet && + subPath.Kind != ODataPathKind.MediaEntity)) { ODataPath newPath = subPath.Clone(); newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction)); diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs index ad43a9f0..b6fb0e8b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataSegment.cs @@ -47,7 +47,17 @@ public enum ODataSegmentKind /// /// $ref /// - Ref + Ref, + + /// + /// Stream content -> $value + /// + StreamContent, + + /// + /// Stream property + /// + StreamProperty } /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs new file mode 100644 index 00000000..aba66263 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamContentSegment.cs @@ -0,0 +1,24 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Collections.Generic; + +namespace Microsoft.OpenApi.OData.Edm +{ + /// + /// Stream segment. + /// + public class ODataStreamContentSegment : ODataSegment + { + /// + public override ODataSegmentKind Kind => ODataSegmentKind.StreamContent; + + /// + public override string Identifier => "$value"; + + /// + public override string GetPathItemName(OpenApiConvertSettings settings, HashSet parameters) => "$value"; + } +} \ No newline at end of file diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs new file mode 100644 index 00000000..efca6864 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataStreamPropertySegment.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Collections.Generic; +using Microsoft.OpenApi.OData.Common; + +namespace Microsoft.OpenApi.OData.Edm +{ + /// + /// Property Stream segment. + /// + public class ODataStreamPropertySegment : ODataSegment + { + private readonly string _streamPropertyName; + /// + /// Initializes a new instance of class. + /// + /// The name of the stream property. + public ODataStreamPropertySegment(string streamPropertyName) + { + _streamPropertyName = streamPropertyName ?? throw Error.ArgumentNull(nameof(streamPropertyName)); + } + + /// + public override ODataSegmentKind Kind => ODataSegmentKind.StreamProperty; + + /// + public override string Identifier { get => _streamPropertyName; } + + /// + public override string GetPathItemName(OpenApiConvertSettings settings, HashSet parameters) => _streamPropertyName; + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs new file mode 100644 index 00000000..fa6cf701 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs @@ -0,0 +1,109 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Generator; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.OpenApi.OData.Operation +{ + /// + /// Retrieve a media content for an Entity + /// + internal class MediaEntityGetOperationHandler : EntitySetOperationHandler + { + /// + public override OperationType OperationType => OperationType.Get; + + /// + protected override void SetBasicInfo(OpenApiOperation operation) + { + string typeName = EntitySet.EntityType().Name; + + // Summary + operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}"; + + // OperationId + if (Context.Settings.EnableOperationId) + { + string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; + operation.OperationId = EntitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(identifier); + } + + base.SetBasicInfo(operation); + } + + /// + protected override void SetResponses(OpenApiOperation operation) + { + OpenApiSchema schema = null; + + if (Context.Settings.EnableDerivedTypesReferencesForResponses) + { + schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); + } + + if (schema == null) + { + schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + }; + } + + operation.Responses = new OpenApiResponses + { + { + Constants.StatusCode200, + new OpenApiResponse + { + Description = "Retrieved media content", + Content = new Dictionary + { + { + Constants.ApplicationOctetStreamMediaType, + new OpenApiMediaType + { + Schema = schema + } + } + } + } + } + }; + operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse()); + + base.SetResponses(operation); + } + /// + protected override void SetSecurity(OpenApiOperation operation) + { + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + if (read == null) + { + return; + } + + ReadRestrictionsBase readBase = read; + if (read.ReadByKeyRestrictions != null) + { + readBase = read.ReadByKeyRestrictions; + } + + if (readBase == null && readBase.Permissions == null) + { + return; + } + + operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList(); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs new file mode 100644 index 00000000..a8ca7cf9 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs @@ -0,0 +1,104 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Collections.Generic; +using System.Linq; +using Microsoft.OData.Edm; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Generator; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; + +namespace Microsoft.OpenApi.OData.Operation +{ + /// + /// Update a media content for an Entity + /// + internal class MediaEntityPutOperationHandler : EntitySetOperationHandler + { + /// + public override OperationType OperationType => OperationType.Put; + + /// + protected override void SetBasicInfo(OpenApiOperation operation) + { + string typeName = EntitySet.EntityType().Name; + + // Summary + operation.Summary = $"Update media content for {typeName} in {EntitySet.Name}"; + + // OperationId + if (Context.Settings.EnableOperationId) + { + string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; + operation.OperationId = EntitySet.Name + "." + typeName + ".Update" + Utils.UpperFirstChar(identifier); + } + + base.SetBasicInfo(operation); + } + + /// + protected override void SetRequestBody(OpenApiOperation operation) + { + OpenApiSchema schema = null; + + if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) + { + schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); + } + + if (schema == null) + { + schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + }; + } + + operation.RequestBody = new OpenApiRequestBody + { + Required = true, + Description = "New media content.", + Content = new Dictionary + { + { + Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + { + Schema = schema + } + } + } + }; + + base.SetRequestBody(operation); + } + + /// + protected override void SetResponses(OpenApiOperation operation) + { + operation.Responses = new OpenApiResponses + { + { Constants.StatusCode204, Constants.StatusCode204.GetResponse() }, + { Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse() } + }; + + base.SetResponses(operation); + } + + /// + protected override void SetSecurity(OpenApiOperation operation) + { + UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); + if (update == null || update.Permissions == null) + { + return; + } + + operation.Security = Context.CreateSecurityRequirements(update.Permissions).ToList(); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs index 763f84a8..3d3abce2 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs @@ -76,6 +76,13 @@ public OperationHandlerProvider() {OperationType.Post, new RefPostOperationHandler() }, {OperationType.Delete, new RefDeleteOperationHandler() } }; + + // media entity operation (Get|Put) + _handlers[ODataPathKind.MediaEntity] = new Dictionary + { + {OperationType.Get, new MediaEntityGetOperationHandler() }, + {OperationType.Put, new MediaEntityPutOperationHandler() } + }; } /// diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs new file mode 100644 index 00000000..24d75c5c --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs @@ -0,0 +1,38 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; + +namespace Microsoft.OpenApi.OData.PathItem +{ + /// + /// Create a for a media entity. + /// + internal class MediaEntityPathItemHandler : EntitySetPathItemHandler + { + /// + protected override ODataPathKind HandleKind => ODataPathKind.MediaEntity; + + /// + protected override void SetOperations(OpenApiPathItem item) + { + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet); + if (read == null || + (read.ReadByKeyRestrictions == null && read.IsReadable) || + (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.IsReadable)) + { + AddOperation(item, OperationType.Get); + } + + UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet); + if (update == null || update.IsUpdatable) + { + AddOperation(item, OperationType.Put); + } + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs index 380fbdcb..5cf3d570 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs @@ -36,6 +36,9 @@ internal class PathItemHandlerProvider : IPathItemHandlerProvider // Edm Ref { ODataPathKind.Ref, new RefPathItemHandler() }, + // Media Entity + {ODataPathKind.MediaEntity, new MediaEntityPathItemHandler() }, + // Unknown { ODataPathKind.Unknown, null }, }; diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs index e17177af..df679253 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs @@ -4,13 +4,12 @@ // ------------------------------------------------------------ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; +using System.Xml.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OData.Edm.Validation; using Microsoft.OpenApi.OData.Tests; using Xunit; @@ -45,7 +44,7 @@ public void GetPathsForGraphBetaModelReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(4583, paths.Count()); + Assert.Equal(4585, paths.Count()); } [Fact] @@ -84,7 +83,7 @@ public void GetPathsWithSingletonWorks() public void GetPathsWithBoundFunctionOperationWorks() { // Arrange - string boundFunction = + string boundFunction = @" @@ -182,6 +181,44 @@ public void GetPathsWithNavigationPropertytWorks() Assert.Contains("/Orders({id})/MultipleCustomers/$ref", pathItems); } + [Theory] + [InlineData(true, "Logo")] + [InlineData(false, "Logo")] + [InlineData(true, "Content")] + [InlineData(false, "Content")] + public void GetPathsWithStreamPropertyAndWithEntityHasStreamWorks(bool hasStream, string streamPropName) + { + // Arrange + IEdmModel model = GetEdmModel(hasStream, streamPropName); + ODataPathProvider provider = new ODataPathProvider(); + + // Act + var paths = provider.GetPaths(model); + + // Assert + Assert.NotNull(paths); + + if (hasStream && !streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase)) + { + Assert.Equal(4, paths.Count()); + Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/$value", "/Todos({Id})/Logo" }, + paths.Select(p => p.GetPathItemName())); + } + else if ((hasStream && streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase)) || + (!hasStream && streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase))) + { + Assert.Equal(3, paths.Count()); + Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/Content" }, + paths.Select(p => p.GetPathItemName())); + } + else // !hasStream && !streamPropName.Equals("Content") + { + Assert.Equal(3, paths.Count()); + Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/Logo" }, + paths.Select(p => p.GetPathItemName())); + } + } + private static IEdmModel GetEdmModel(string schemaElement, string containerElement) { string template = @" @@ -198,12 +235,35 @@ private static IEdmModel GetEdmModel(string schemaElement, string containerEleme {1} "; - string schema = String.Format(template, schemaElement, containerElement); - IEdmModel parsedModel; - IEnumerable errors; - bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out parsedModel, out errors); + string schema = string.Format(template, schemaElement, containerElement); + bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out IEdmModel parsedModel, out _); Assert.True(parsed); return parsedModel; } + + private static IEdmModel GetEdmModel(bool hasStream, string streamPropName) + { + string template = @" + + + + + + + + + + + + + + + +"; + string modelText = string.Format(template, hasStream, streamPropName); + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); + Assert.True(result); + return model; + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs index 255d95d9..57045cda 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathTests.cs @@ -105,7 +105,7 @@ public void ODataPathLastSegmentWorks() } [Fact] - public void KindPropertyReturnsUnknow() + public void KindPropertyReturnsUnknown() { // Arrange ODataKeySegment keySegment = new ODataKeySegment(_simpleKeyEntityType); @@ -198,6 +198,32 @@ public void KindPropertyReturnsOperationImport() Assert.Equal(ODataPathKind.OperationImport, path.Kind); } + [Fact] + public void KindPropertyReturnsStreamProperty() + { + // Arrange + ODataNavigationSourceSegment nsSegment = new ODataNavigationSourceSegment(_simpleKeyEntitySet); + ODataKeySegment keySegment = new ODataKeySegment(_simpleKeyEntityType); + ODataStreamPropertySegment streamPropSegment = new ODataStreamPropertySegment("Logo"); + ODataPath path = new ODataPath(nsSegment, keySegment, streamPropSegment); + + // Act & Assert + Assert.Equal(ODataPathKind.MediaEntity, path.Kind); + } + + [Fact] + public void KindPropertyReturnsStreamContent() + { + // Arrange + ODataNavigationSourceSegment nsSegment = new ODataNavigationSourceSegment(_simpleKeyEntitySet); + ODataKeySegment keySegment = new ODataKeySegment(_simpleKeyEntityType); + ODataStreamContentSegment streamContSegment = new ODataStreamContentSegment(); + ODataPath path = new ODataPath(nsSegment, keySegment, streamContSegment); + + // Act & Assert + Assert.Equal(ODataPathKind.MediaEntity, path.Kind); + } + [Theory] [InlineData(true, true, "/Orders/{Order-Id}")] [InlineData(true, false, "/Orders/{Id}")] diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamContentSegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamContentSegmentTests.cs new file mode 100644 index 00000000..92439491 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamContentSegmentTests.cs @@ -0,0 +1,57 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Xunit; + +namespace Microsoft.OpenApi.OData.Edm.Tests +{ + public class ODataStreamContentSegmentTests + { + private readonly EdmEntityType _todo; + + public ODataStreamContentSegmentTests() + { + _todo = new EdmEntityType("microsoft.graph", "Todo", + new EdmEntityType("microsoft.graph", "Task"), + isAbstract: false, + isOpen: false, + hasStream: true); + _todo.AddKeys(_todo.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String)); + _todo.AddKeys(_todo.AddStructuralProperty("Logo", EdmPrimitiveTypeKind.Stream)); + _todo.AddKeys(_todo.AddStructuralProperty("Description", EdmPrimitiveTypeKind.String)); + } + + [Fact] + public void StreamContentSegmentIdentifierPropertyReturnsCorrectDefaultValue() + { + // Arrange & Act + ODataStreamContentSegment segment = new ODataStreamContentSegment(); + + // Assert + Assert.Same("$value", segment.Identifier); + } + + [Fact] + public void KindPropertyReturnsStreamContentEnumMember() + { + // Arrange & Act + ODataStreamContentSegment segment = new ODataStreamContentSegment(); + + // Assert + Assert.Equal(ODataSegmentKind.StreamContent, segment.Kind); + } + + [Fact] + public void GetPathItemNameReturnsCorrectDefaultStreamContentValue() + { + // Arrange & Act + ODataStreamContentSegment segment = new ODataStreamContentSegment(); + + // Assert + Assert.Equal("$value", segment.GetPathItemName(new OpenApiConvertSettings())); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamPropertySegmentTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamPropertySegmentTests.cs new file mode 100644 index 00000000..d5858a1b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataStreamPropertySegmentTests.cs @@ -0,0 +1,70 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.Linq; +using Microsoft.OData.Edm; +using Xunit; + +namespace Microsoft.OpenApi.OData.Edm.Tests +{ + public class ODataStreamPropertySegmentTests + { + private readonly EdmEntityType _todo; + + public ODataStreamPropertySegmentTests() + { + _todo = new EdmEntityType("microsoft.graph", "Todo"); + _todo.AddKeys(_todo.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String)); + _todo.AddKeys(_todo.AddStructuralProperty("Logo", EdmPrimitiveTypeKind.Stream)); + _todo.AddKeys(_todo.AddStructuralProperty("Description", EdmPrimitiveTypeKind.String)); + } + + [Fact] + public void StreamPropertySegmentConstructorThrowsArgumentNull() + { + Assert.Throws("streamPropertyName", () => new ODataStreamPropertySegment(null)); + } + + [Fact] + public void StreamPropertySegmentIdentifierPropertyReturnsStreamPropertyNameOfEntity() + { + // Arrange + var streamPropName = _todo.DeclaredStructuralProperties().First(c => c.Name == "Logo").Name; + + // Act + ODataStreamPropertySegment segment = new ODataStreamPropertySegment(streamPropName); + + // Assert + Assert.Same(streamPropName, segment.Identifier); + } + + [Fact] + public void KindPropertyReturnsStreamPropertyEnumMember() + { + // Arrange + var streamPropName = _todo.DeclaredStructuralProperties().First(c => c.Name == "Logo").Name; + + // Act + ODataStreamPropertySegment segment = new ODataStreamPropertySegment(streamPropName); + + // Assert + Assert.Equal(ODataSegmentKind.StreamProperty, segment.Kind); + } + + [Fact] + public void GetPathItemNameReturnsCorrectStreamPropertyNameOfEntity() + { + // Arrange + var streamPropName = _todo.DeclaredStructuralProperties().First(c => c.Name == "Logo").Name; + + // Act + ODataStreamPropertySegment segment = new ODataStreamPropertySegment(streamPropName); + + // Assert + Assert.Equal(streamPropName, segment.GetPathItemName(new OpenApiConvertSettings())); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs new file mode 100644 index 00000000..1e9f2522 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs @@ -0,0 +1,89 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OpenApi.OData.Edm; +using System.Linq; +using System.Xml.Linq; +using Xunit; + +namespace Microsoft.OpenApi.OData.Operation.Tests +{ + public class MediaEntityGetOperationHandlerTests + { + private readonly MediaEntityGetOperationHandler _operationalHandler = new MediaEntityGetOperationHandler(); + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOperationId) + { + // Arrange + IEdmModel model = GetEdmModel(); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + EnableOperationId = enableOperationId + }; + + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet todos = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(todos); + + IEdmEntityType todo = model.SchemaElements.OfType().First(c => c.Name == "Todo"); + IEdmStructuralProperty sp = todo.DeclaredStructuralProperties().First(c => c.Name == "Logo"); + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(todos), + new ODataKeySegment(todos.EntityType()), + new ODataStreamPropertySegment(sp.Name)); + + // Act + var getOperation = _operationalHandler.CreateOperation(context, path); + + // Assert + Assert.NotNull(getOperation); + Assert.Equal("Get media content for Todo from Todos", getOperation.Summary); + Assert.NotNull(getOperation.Tags); + var tag = Assert.Single(getOperation.Tags); + Assert.Equal("Todos.Todo", tag.Name); + + Assert.NotNull(getOperation.Responses); + Assert.Equal(2, getOperation.Responses.Count); + Assert.Equal(new[] { "200", "default" }, getOperation.Responses.Select(r => r.Key)); + + if (enableOperationId) + { + Assert.Equal("Todos.Todo.GetLogo", getOperation.OperationId); + } + else + { + Assert.Null(getOperation.OperationId); + } + } + + public static IEdmModel GetEdmModel() + { + const string modelText = @" + + + + + + + + + + + + + + + +"; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs new file mode 100644 index 00000000..14fe92d4 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs @@ -0,0 +1,63 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Microsoft.OpenApi.OData.Edm; +using System.Linq; +using Xunit; + +namespace Microsoft.OpenApi.OData.Operation.Tests +{ + public class MediaEntityPutOperationHandlerTests + { + private readonly MediaEntityPutOperationHandler _operationalHandler = new MediaEntityPutOperationHandler(); + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperationId) + { + // Arrange + IEdmModel model = MediaEntityGetOperationHandlerTests.GetEdmModel(); + OpenApiConvertSettings settings = new OpenApiConvertSettings + { + EnableOperationId = enableOperationId + }; + + ODataContext context = new ODataContext(model, settings); + IEdmEntitySet todos = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(todos); + + IEdmEntityType todo = model.SchemaElements.OfType().First(c => c.Name == "Todo"); + IEdmStructuralProperty sp = todo.DeclaredStructuralProperties().First(c => c.Name == "Logo"); + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(todos), + new ODataKeySegment(todos.EntityType()), + new ODataStreamPropertySegment(sp.Name)); + + // Act + var getOperation = _operationalHandler.CreateOperation(context, path); + + // Assert + Assert.NotNull(getOperation); + Assert.Equal("Update media content for Todo in Todos", getOperation.Summary); + Assert.NotNull(getOperation.Tags); + var tag = Assert.Single(getOperation.Tags); + Assert.Equal("Todos.Todo", tag.Name); + + Assert.NotNull(getOperation.Responses); + Assert.Equal(2, getOperation.Responses.Count); + Assert.Equal(new[] { "204", "default" }, getOperation.Responses.Select(r => r.Key)); + + if (enableOperationId) + { + Assert.Equal("Todos.Todo.UpdateLogo", getOperation.OperationId); + } + else + { + Assert.Null(getOperation.OperationId); + } + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs index ca6e588b..f28668d4 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/OperationHandlerProviderTests.cs @@ -32,6 +32,8 @@ public class OperationHandlerProviderTests [InlineData(ODataPathKind.Ref, OperationType.Delete, typeof(RefDeleteOperationHandler))] [InlineData(ODataPathKind.Ref, OperationType.Get, typeof(RefGetOperationHandler))] [InlineData(ODataPathKind.Ref, OperationType.Put, typeof(RefPutOperationHandler))] + [InlineData(ODataPathKind.MediaEntity, OperationType.Get, typeof(MediaEntityGetOperationHandler))] + [InlineData(ODataPathKind.MediaEntity, OperationType.Put, typeof(MediaEntityPutOperationHandler))] public void GetHandlerReturnsCorrectOperationHandlerType(ODataPathKind pathKind, OperationType operationType, Type handlerType) { // Arrange diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs new file mode 100644 index 00000000..53f164f4 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs @@ -0,0 +1,206 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Properties; +using System; +using System.Linq; +using System.Xml.Linq; +using Xunit; + +namespace Microsoft.OpenApi.OData.PathItem.Tests +{ + public class MediaEntityPathItemHandlerTests + { + private readonly MediaEntityPathItemHandler _pathItemHandler = new MyMediaEntityPathItemHandler(); + + [Fact] + public void CreatePathItemThrowsForNullContext() + { + // Arrange & Act & Assert + Assert.Throws("context", + () => _pathItemHandler.CreatePathItem(context: null, path: new ODataPath())); + } + + [Fact] + public void CreatePathItemThrowsForNullPath() + { + // Arrange & Act & Assert + Assert.Throws("path", + () => _pathItemHandler.CreatePathItem(new ODataContext(EdmCoreModel.Instance), path: null)); + } + + [Fact] + public void CreatePathItemThrowsForNonMediaEntityPath() + { + // Arrange + IEdmModel model = GetEdmModel(""); + ODataContext context = new ODataContext(model); + var entitySet = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(entitySet); // guard + var path = new ODataPath(new ODataNavigationSourceSegment(entitySet)); + + // Act + void test() => _pathItemHandler.CreatePathItem(context, path); + + // Assert + var exception = Assert.Throws(test); + Assert.Equal(string.Format(SRResource.InvalidPathKindForPathItemHandler, _pathItemHandler.GetType().Name, path.Kind), exception.Message); + } + + [Fact] + public void CreateMediaEntityPathItemReturnsCorrectItem() + { + // Arrange + IEdmModel model = GetEdmModel(""); + ODataContext context = new ODataContext(model); + var entitySet = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType(); + + IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataStreamPropertySegment(sp.Name)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(2, pathItem.Operations.Count); + Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Put }, + pathItem.Operations.Select(o => o.Key)); + } + + [Theory] + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Put })] + [InlineData(false, new OperationType[] { OperationType.Put })] + public void CreateMediaEntityPathItemWorksForReadByKeyRestrictionsCapablities(bool readable, OperationType[] expected) + { + // Arrange + string annotation = $@" + + + + + + + + +"; + + // Assert + VerifyPathItemOperationsForStreamPropertySegment(annotation, expected); + VerifyPathItemOperationsForStreamContentSegment(annotation, expected); + } + + [Theory] + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Put })] + [InlineData(false, new OperationType[] { OperationType.Get })] + public void CreateMediaEntityPathItemWorksForUpdateRestrictionsCapablities(bool updatable, OperationType[] expected) + { + // Arrange + string annotation = $@" + + + + +"; + + // Assert + VerifyPathItemOperationsForStreamPropertySegment(annotation, expected); + VerifyPathItemOperationsForStreamContentSegment(annotation, expected); + } + + private void VerifyPathItemOperationsForStreamPropertySegment(string annotation, OperationType[] expected) + { + // Arrange + IEdmModel model = GetEdmModel(annotation); + ODataContext context = new ODataContext(model); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType(); + + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataStreamContentSegment()); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); + } + + private void VerifyPathItemOperationsForStreamContentSegment(string annotation, OperationType[] expected) + { + // Arrange + IEdmModel model = GetEdmModel(annotation); + ODataContext context = new ODataContext(model); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); + Assert.NotNull(entitySet); // guard + IEdmEntityType entityType = entitySet.EntityType(); + + IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), + new ODataKeySegment(entityType), + new ODataStreamPropertySegment(sp.Name)); + + // Act + var pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + + Assert.NotNull(pathItem.Operations); + Assert.NotEmpty(pathItem.Operations); + Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + + + + + + + + + + + + {0} + + + +"; + string modelText = string.Format(template, annotation); + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); + Assert.True(result); + return model; + } + } + + internal class MyMediaEntityPathItemHandler : MediaEntityPathItemHandler + { + protected override void AddOperation(OpenApiPathItem item, OperationType operationType) + { + item.AddOperation(operationType, new OpenApiOperation()); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/PathItemHandlerProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/PathItemHandlerProviderTests.cs index 4722b86a..3de9155f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/PathItemHandlerProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/PathItemHandlerProviderTests.cs @@ -19,6 +19,7 @@ public class PathItemHandlerProviderTests [InlineData(ODataPathKind.Operation, typeof(OperationPathItemHandler))] [InlineData(ODataPathKind.OperationImport, typeof(OperationImportPathItemHandler))] [InlineData(ODataPathKind.Ref, typeof(RefPathItemHandler))] + [InlineData(ODataPathKind.MediaEntity, typeof(MediaEntityPathItemHandler))] public void GetHandlerReturnsCorrectHandlerType(ODataPathKind pathKind, Type handlerType) { // Arrange From 87f1d1de7575cb4766eb52aa87a57be33bd70861 Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 31 Aug 2020 04:35:52 -0400 Subject: [PATCH 07/12] Limit operations to only include item by key for contained collections and $ref for non-contained collections (#6) * Fixed non-contained reference collections * Fix some tests * Fix tests * Fixed test * Updates based on review Co-authored-by: Darrel Miller --- .../Edm/ODataPathProvider.cs | 49 +- .../Edm/ODataPathProviderTests.cs | 37 +- .../Resources/Multiple.Schema.OpenApi.V2.json | 263 -- .../Resources/Multiple.Schema.OpenApi.V2.yaml | 200 -- .../Resources/Multiple.Schema.OpenApi.json | 335 --- .../Resources/Multiple.Schema.OpenApi.yaml | 248 -- .../Resources/TripService.OData.xml | 2 +- .../Resources/TripService.OpenApi.V2.json | 1626 ++++++---- .../Resources/TripService.OpenApi.V2.yaml | 843 ++++-- .../Resources/TripService.OpenApi.json | 2642 ++++++++++------- .../Resources/TripService.OpenApi.yaml | 1040 +++++-- 11 files changed, 4096 insertions(+), 3189 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs index a6b877b9..18c1791e 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs @@ -254,40 +254,41 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr newPath.Push(ODataRefSegment.Instance); // $ref AppendPath(newPath); } - - // append a navigation property key. - IEdmEntityType navEntityType = navigationProperty.ToEntityType(); - if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) + else { - currentPath.Push(new ODataKeySegment(navEntityType)); - AppendPath(currentPath.Clone()); + IEdmEntityType navEntityType = navigationProperty.ToEntityType(); - if (!navigationProperty.ContainsTarget) + // append a navigation property key. + if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { - // TODO: Shall we add "$ref" after {key}, and only support delete? - // ODataPath newPath = currentPath.Clone(); - // newPath.Push(ODataRefSegment.Instance); // $ref - // AppendPath(newPath); + currentPath.Push(new ODataKeySegment(navEntityType)); + AppendPath(currentPath.Clone()); + + if (!navigationProperty.ContainsTarget) + { + // TODO: Shall we add "$ref" after {key}, and only support delete? + // ODataPath newPath = currentPath.Clone(); + // newPath.Push(ODataRefSegment.Instance); // $ref + // AppendPath(newPath); + } } - } - if (shouldExpand) - { - // expand to sub navigation properties - foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties()) + if (shouldExpand) { - if (CanFilter(subNavProperty)) + // expand to sub navigation properties + foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties()) { - RetrieveNavigationPropertyPaths(subNavProperty, currentPath); + if (CanFilter(subNavProperty)) + { + RetrieveNavigationPropertyPaths(subNavProperty, currentPath); + } } } + if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) + { + currentPath.Pop(); + } } - - if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) - { - currentPath.Pop(); - } - currentPath.Pop(); } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs index df679253..a740a7d9 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs @@ -44,7 +44,7 @@ public void GetPathsForGraphBetaModelReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(4585, paths.Count()); + Assert.Equal(4457, paths.Count()); } [Fact] @@ -149,7 +149,7 @@ public void GetPathsWithUnboundOperationImportWorks() } [Fact] - public void GetPathsWithNavigationPropertytWorks() + public void GetPathsWithNonContainedNavigationPropertytWorks() { // Arrange string entityType = @@ -171,16 +171,45 @@ public void GetPathsWithNavigationPropertytWorks() // Assert Assert.NotNull(paths); - Assert.Equal(9, paths.Count()); + Assert.Equal(8, paths.Count()); var pathItems = paths.Select(p => p.GetPathItemName()).ToList(); Assert.Contains("/Orders({id})/MultipleCustomers", pathItems); - Assert.Contains("/Orders({id})/MultipleCustomers({ID})", pathItems); Assert.Contains("/Orders({id})/SingleCustomer", pathItems); Assert.Contains("/Orders({id})/SingleCustomer/$ref", pathItems); Assert.Contains("/Orders({id})/MultipleCustomers/$ref", pathItems); } + [Fact] + public void GetPathsWithContainedNavigationPropertytWorks() + { + // Arrange + string entityType = +@" + + + + + + "; + + string entitySet = @""; + IEdmModel model = GetEdmModel(entityType, entitySet); + ODataPathProvider provider = new ODataPathProvider(); + + // Act + var paths = provider.GetPaths(model); + + // Assert + Assert.NotNull(paths); + Assert.Equal(7, paths.Count()); + + var pathItems = paths.Select(p => p.GetPathItemName()).ToList(); + Assert.Contains("/Orders({id})/MultipleCustomers", pathItems); + Assert.Contains("/Orders({id})/MultipleCustomers({ID})", pathItems); + Assert.Contains("/Orders({id})/SingleCustomer", pathItems); + } + [Theory] [InlineData(true, "Logo")] [InlineData(false, "Logo")] diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json index 0ce89148..c88d2f0c 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.json @@ -773,96 +773,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Documents({Id})/Revisions({Id1})": { - "get": { - "tags": [ - "Documents.RevisionDto" - ], - "summary": "Get Revisions from Documents", - "operationId": "Documents.GetRevisions", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of DocumentDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "in": "path", - "name": "Id1", - "description": "key: Id of RevisionDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "RevisionDto" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "Id", - "Number", - "DocumentId", - "DocumentName", - "DocumentDescription", - "CreationDate", - "CreatedBy", - "IsReviewed", - "ReviewedBy", - "ReviewedDate", - "IsApproved", - "ApprovedBy", - "ApprovedDate", - "IsRejected", - "RejectedBy", - "RejectedDate", - "DomainId", - "Document" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Document" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Siterra.Documents.App.DTO.RevisionDto" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Documents({Id})/Revisions/$ref": { "get": { "tags": [ @@ -1465,89 +1375,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Libraries({Id})/Documents({Id1})": { - "get": { - "tags": [ - "Libraries.DocumentDto" - ], - "summary": "Get Documents from Libraries", - "operationId": "Libraries.GetDocuments", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of LibraryDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "LibraryDto" - }, - { - "in": "path", - "name": "Id1", - "description": "key: Id of DocumentDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "Id", - "Name", - "Description", - "Filename", - "NumberOfRevisions", - "Suffix", - "DomainId", - "ModificationDate", - "ModifiedBy", - "Tags", - "Revisions" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Revisions" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Siterra.Documents.App.DTO.DocumentDto" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Libraries({Id})/Documents/$ref": { "get": { "tags": [ @@ -2733,96 +2560,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Tasks({Id})/Revisions({Id1})": { - "get": { - "tags": [ - "Tasks.RevisionDto" - ], - "summary": "Get Revisions from Tasks", - "operationId": "Tasks.GetRevisions", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "Id", - "description": "key: Id of DocumentDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "in": "path", - "name": "Id1", - "description": "key: Id of RevisionDto", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "RevisionDto" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "Id", - "Number", - "DocumentId", - "DocumentName", - "DocumentDescription", - "CreationDate", - "CreatedBy", - "IsReviewed", - "ReviewedBy", - "ReviewedDate", - "IsApproved", - "ApprovedBy", - "ApprovedDate", - "IsRejected", - "RejectedBy", - "RejectedDate", - "DomainId", - "Document" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Document" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Siterra.Documents.App.DTO.RevisionDto" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Tasks({Id})/Revisions/$ref": { "get": { "tags": [ diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml index 0c6f7654..4397f1f3 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.V2.yaml @@ -549,75 +549,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/Documents({Id})/Revisions({Id1})': - get: - tags: - - Documents.RevisionDto - summary: Get Revisions from Documents - operationId: Documents.GetRevisions - produces: - - application/json - parameters: - - in: path - name: Id - description: 'key: Id of DocumentDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: DocumentDto - - in: path - name: Id1 - description: 'key: Id of RevisionDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: RevisionDto - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - Id - - Number - - DocumentId - - DocumentName - - DocumentDescription - - CreationDate - - CreatedBy - - IsReviewed - - ReviewedBy - - ReviewedDate - - IsApproved - - ApprovedBy - - ApprovedDate - - IsRejected - - RejectedBy - - RejectedDate - - DomainId - - Document - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Document - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Siterra.Documents.App.DTO.RevisionDto' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation '/Documents({Id})/Revisions/$ref': get: tags: @@ -1054,68 +985,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/Libraries({Id})/Documents({Id1})': - get: - tags: - - Libraries.DocumentDto - summary: Get Documents from Libraries - operationId: Libraries.GetDocuments - produces: - - application/json - parameters: - - in: path - name: Id - description: 'key: Id of LibraryDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: LibraryDto - - in: path - name: Id1 - description: 'key: Id of DocumentDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: DocumentDto - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - Id - - Name - - Description - - Filename - - NumberOfRevisions - - Suffix - - DomainId - - ModificationDate - - ModifiedBy - - Tags - - Revisions - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Revisions - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Siterra.Documents.App.DTO.DocumentDto' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation '/Libraries({Id})/Documents/$ref': get: tags: @@ -1984,75 +1853,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/Tasks({Id})/Revisions({Id1})': - get: - tags: - - Tasks.RevisionDto - summary: Get Revisions from Tasks - operationId: Tasks.GetRevisions - produces: - - application/json - parameters: - - in: path - name: Id - description: 'key: Id of DocumentDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: DocumentDto - - in: path - name: Id1 - description: 'key: Id of RevisionDto' - required: true - type: integer - format: int32 - maximum: 2147483647 - minimum: -2147483648 - x-ms-docs-key-type: RevisionDto - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - Id - - Number - - DocumentId - - DocumentName - - DocumentDescription - - CreationDate - - CreatedBy - - IsReviewed - - ReviewedBy - - ReviewedDate - - IsApproved - - ApprovedBy - - ApprovedDate - - IsRejected - - RejectedBy - - RejectedDate - - DomainId - - Document - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Document - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Siterra.Documents.App.DTO.RevisionDto' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation '/Tasks({Id})/Revisions/$ref': get: tags: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json index 055c92df..6381aa23 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.json @@ -867,120 +867,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Documents({Id})/Revisions({Id1})": { - "get": { - "tags": [ - "Documents.RevisionDto" - ], - "summary": "Get Revisions from Documents", - "operationId": "Documents.GetRevisions", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of DocumentDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "name": "Id1", - "in": "path", - "description": "key: Id of RevisionDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "RevisionDto" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "Id", - "Number", - "DocumentId", - "DocumentName", - "DocumentDescription", - "CreationDate", - "CreatedBy", - "IsReviewed", - "ReviewedBy", - "ReviewedDate", - "IsApproved", - "ApprovedBy", - "ApprovedDate", - "IsRejected", - "RejectedBy", - "RejectedDate", - "DomainId", - "Document" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Document" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Siterra.Documents.App.DTO.RevisionDto" - } - } - }, - "links": { - "Document": { - "operationId": "Documents.Revisions.GetDocument", - "parameters": { - "Id": "$request.path.Id", - "Id1": "$request.path.Id1" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Documents({Id})/Revisions/$ref": { "get": { "tags": [ @@ -1651,113 +1537,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Libraries({Id})/Documents({Id1})": { - "get": { - "tags": [ - "Libraries.DocumentDto" - ], - "summary": "Get Documents from Libraries", - "operationId": "Libraries.GetDocuments", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of LibraryDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "LibraryDto" - }, - { - "name": "Id1", - "in": "path", - "description": "key: Id of DocumentDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "Id", - "Name", - "Description", - "Filename", - "NumberOfRevisions", - "Suffix", - "DomainId", - "ModificationDate", - "ModifiedBy", - "Tags", - "Revisions" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Revisions" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Siterra.Documents.App.DTO.DocumentDto" - } - } - }, - "links": { - "Revisions": { - "operationId": "Libraries.Documents.ListRevisions", - "parameters": { - "Id": "$request.path.Id", - "Id1": "$request.path.Id1" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Libraries({Id})/Documents/$ref": { "get": { "tags": [ @@ -3139,120 +2918,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Tasks({Id})/Revisions({Id1})": { - "get": { - "tags": [ - "Tasks.RevisionDto" - ], - "summary": "Get Revisions from Tasks", - "operationId": "Tasks.GetRevisions", - "parameters": [ - { - "name": "Id", - "in": "path", - "description": "key: Id of DocumentDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "DocumentDto" - }, - { - "name": "Id1", - "in": "path", - "description": "key: Id of RevisionDto", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "RevisionDto" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "Id", - "Number", - "DocumentId", - "DocumentName", - "DocumentDescription", - "CreationDate", - "CreatedBy", - "IsReviewed", - "ReviewedBy", - "ReviewedDate", - "IsApproved", - "ApprovedBy", - "ApprovedDate", - "IsRejected", - "RejectedBy", - "RejectedDate", - "DomainId", - "Document" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Document" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Siterra.Documents.App.DTO.RevisionDto" - } - } - }, - "links": { - "Document": { - "operationId": "Tasks.Revisions.GetDocument", - "parameters": { - "Id": "$request.path.Id", - "Id1": "$request.path.Id1" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Tasks({Id})/Revisions/$ref": { "get": { "tags": [ diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml index feeaf017..8fa81a80 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/Multiple.Schema.OpenApi.yaml @@ -609,91 +609,6 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - '/Documents({Id})/Revisions({Id1})': - get: - tags: - - Documents.RevisionDto - summary: Get Revisions from Documents - operationId: Documents.GetRevisions - parameters: - - name: Id - in: path - description: 'key: Id of DocumentDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: DocumentDto - - name: Id1 - in: path - description: 'key: Id of RevisionDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: RevisionDto - - name: $select - in: query - description: Select properties to be returned - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - Id - - Number - - DocumentId - - DocumentName - - DocumentDescription - - CreationDate - - CreatedBy - - IsReviewed - - ReviewedBy - - ReviewedDate - - IsApproved - - ApprovedBy - - ApprovedDate - - IsRejected - - RejectedBy - - RejectedDate - - DomainId - - Document - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Document - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - $ref: '#/components/schemas/Siterra.Documents.App.DTO.RevisionDto' - links: - Document: - operationId: Documents.Revisions.GetDocument - parameters: - Id: $request.path.Id - Id1: $request.path.Id1 - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation '/Documents({Id})/Revisions/$ref': get: tags: @@ -1174,84 +1089,6 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - '/Libraries({Id})/Documents({Id1})': - get: - tags: - - Libraries.DocumentDto - summary: Get Documents from Libraries - operationId: Libraries.GetDocuments - parameters: - - name: Id - in: path - description: 'key: Id of LibraryDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: LibraryDto - - name: Id1 - in: path - description: 'key: Id of DocumentDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: DocumentDto - - name: $select - in: query - description: Select properties to be returned - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - Id - - Name - - Description - - Filename - - NumberOfRevisions - - Suffix - - DomainId - - ModificationDate - - ModifiedBy - - Tags - - Revisions - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Revisions - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - $ref: '#/components/schemas/Siterra.Documents.App.DTO.DocumentDto' - links: - Revisions: - operationId: Libraries.Documents.ListRevisions - parameters: - Id: $request.path.Id - Id1: $request.path.Id1 - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation '/Libraries({Id})/Documents/$ref': get: tags: @@ -2245,91 +2082,6 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - '/Tasks({Id})/Revisions({Id1})': - get: - tags: - - Tasks.RevisionDto - summary: Get Revisions from Tasks - operationId: Tasks.GetRevisions - parameters: - - name: Id - in: path - description: 'key: Id of DocumentDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: DocumentDto - - name: Id1 - in: path - description: 'key: Id of RevisionDto' - required: true - schema: - maximum: 2147483647 - minimum: -2147483648 - type: integer - format: int32 - x-ms-docs-key-type: RevisionDto - - name: $select - in: query - description: Select properties to be returned - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - Id - - Number - - DocumentId - - DocumentName - - DocumentDescription - - CreationDate - - CreatedBy - - IsReviewed - - ReviewedBy - - ReviewedDate - - IsApproved - - ApprovedBy - - ApprovedDate - - IsRejected - - RejectedBy - - RejectedDate - - DomainId - - Document - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Document - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - $ref: '#/components/schemas/Siterra.Documents.App.DTO.RevisionDto' - links: - Document: - operationId: Tasks.Revisions.GetDocument - parameters: - Id: $request.path.Id - Id1: $request.path.Id1 - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation '/Tasks({Id})/Revisions/$ref': get: tags: diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OData.xml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OData.xml index fc90c82d..adf4ae02 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OData.xml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OData.xml @@ -19,7 +19,7 @@ - + diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json index c26fef34..46ef53ec 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.json @@ -955,80 +955,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Me/Friends/{UserName}": { - "get": { - "tags": [ - "Me.Person" - ], - "summary": "Get Friends from Me", - "operationId": "Me.GetFriends", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Me/Friends/$ref": { "get": { "tags": [ @@ -1446,6 +1372,42 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "Me.Trip" + ], + "summary": "Create new navigation property to Trips for Me", + "operationId": "Me.CreateTrips", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "New navigation property", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + ], + "responses": { + "201": { + "description": "Created navigation property.", + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/Me/Trips/{TripId}": { @@ -1516,6 +1478,82 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "patch": { + "tags": [ + "Me.Trip" + ], + "summary": "Update the navigation property Trips in Me", + "operationId": "Me.UpdateTrips", + "consumes": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property values", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "delete": { + "tags": [ + "Me.Trip" + ], + "summary": "Delete navigation property Trips for Me", + "operationId": "Me.DeleteTrips", + "parameters": [ + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "header", + "name": "If-Match", + "description": "ETag", + "type": "string" + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/Me/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { @@ -1558,17 +1596,28 @@ "x-ms-docs-operation-type": "function" } }, - "/Me/Trips/$ref": { + "/Me/Trips/{TripId}/PlanItems": { "get": { "tags": [ - "Me.Trip" + "Me.Trips.PlanItem" ], - "summary": "Get ref of Trips from Me", - "operationId": "Me.ListRefTrips", + "summary": "Get PlanItems from Me", + "operationId": "Me.Trips.ListPlanItems", "produces": [ "application/json" ], "parameters": [ + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, { "$ref": "#/parameters/top" }, @@ -1591,22 +1640,44 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$select", + "description": "Select properties to be returned", + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "ConfirmationCode", + "StartsAt", + "EndsAt", + "Duration" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$expand", + "description": "Expand related entities", + "type": "array", + "items": { + "enum": [ + "*" ], "type": "string" } @@ -1614,15 +1685,15 @@ ], "responses": { "200": { - "description": "Retrieved navigation property links", + "description": "Retrieved navigation property", "schema": { - "title": "Collection of links of Trip", + "title": "Collection of PlanItem", "type": "object", "properties": { "value": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" } } } @@ -1633,38 +1704,131 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "post": { + } + }, + "/Me/Trips/{TripId}/PlanItems/$ref": { + "get": { "tags": [ - "Me.Trip" - ], - "summary": "Create new navigation property ref to Trips for Me", - "operationId": "Me.CreateRefTrips", - "consumes": [ - "application/json" + "Me.Trips.PlanItem" ], + "summary": "Get ref of PlanItems from Me", + "operationId": "Me.Trips.ListRefPlanItems", "produces": [ "application/json" ], "parameters": [ { - "in": "body", - "name": "body", - "description": "New navigation property ref value", + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", "required": true, - "schema": { - "type": "object", - "additionalProperties": { - "type": "object" - } - } - } - ], - "responses": { - "201": { - "description": "Created navigation property link.", - "schema": { - "type": "object" + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "$ref": "#/parameters/top" + }, + { + "$ref": "#/parameters/skip" + }, + { + "$ref": "#/parameters/search" + }, + { + "$ref": "#/parameters/filter" + }, + { + "$ref": "#/parameters/count" + }, + { + "in": "query", + "name": "$orderby", + "description": "Order items by property values", + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc", + "Duration", + "Duration desc" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property links", + "schema": { + "title": "Collection of links of PlanItem", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "Me.Trips.PlanItem" + ], + "summary": "Create new navigation property ref to PlanItems for Me", + "operationId": "Me.Trips.CreateRefPlanItems", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property ref value", + "required": true, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object" + } + } + } + ], + "responses": { + "201": { + "description": "Created navigation property link.", + "schema": { + "type": "object" } }, "default": { @@ -2288,88 +2452,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/NewComePeople/{UserName}/Friends/{UserName1}": { - "get": { - "tags": [ - "NewComePeople.Person" - ], - "summary": "Get Friends from NewComePeople", - "operationId": "NewComePeople.GetFriends", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "path", - "name": "UserName1", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/NewComePeople/{UserName}/Friends/$ref": { "get": { "tags": [ @@ -2853,6 +2935,50 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "NewComePeople.Trip" + ], + "summary": "Create new navigation property to Trips for NewComePeople", + "operationId": "NewComePeople.CreateTrips", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + ], + "responses": { + "201": { + "description": "Created navigation property.", + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/NewComePeople/{UserName}/Trips/{TripId}": { @@ -2931,16 +3057,14 @@ } }, "x-ms-docs-operation-type": "operation" - } - }, - "/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { - "get": { + }, + "patch": { "tags": [ - "NewComePeople.Functions" + "NewComePeople.Trip" ], - "summary": "Invoke function GetInvolvedPeople", - "operationId": "NewComePeople.Trips.GetInvolvedPeople", - "produces": [ + "summary": "Update the navigation property Trips in NewComePeople", + "operationId": "NewComePeople.UpdateTrips", + "consumes": [ "application/json" ], "parameters": [ @@ -2962,35 +3086,33 @@ "maximum": 2147483647, "minimum": -2147483648, "x-ms-docs-key-type": "Trip" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property values", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } } ], "responses": { - "200": { - "description": "Success", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } + "204": { + "description": "Success" }, "default": { "$ref": "#/responses/error" } }, - "x-ms-docs-operation-type": "function" - } - }, - "/NewComePeople/{UserName}/Trips/$ref": { - "get": { + "x-ms-docs-operation-type": "operation" + }, + "delete": { "tags": [ "NewComePeople.Trip" ], - "summary": "Get ref of Trips from NewComePeople", - "operationId": "NewComePeople.ListRefTrips", - "produces": [ - "application/json" - ], + "summary": "Delete navigation property Trips for NewComePeople", + "operationId": "NewComePeople.DeleteTrips", "parameters": [ { "in": "path", @@ -3001,7 +3123,114 @@ "x-ms-docs-key-type": "Person" }, { - "$ref": "#/parameters/top" + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "header", + "name": "If-Match", + "description": "ETag", + "type": "string" + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { + "get": { + "tags": [ + "NewComePeople.Functions" + ], + "summary": "Invoke function GetInvolvedPeople", + "operationId": "NewComePeople.Trips.GetInvolvedPeople", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "function" + } + }, + "/NewComePeople/{UserName}/Trips/{TripId}/PlanItems": { + "get": { + "tags": [ + "NewComePeople.Trips.PlanItem" + ], + "summary": "Get PlanItems from NewComePeople", + "operationId": "NewComePeople.Trips.ListPlanItems", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "$ref": "#/parameters/top" }, { "$ref": "#/parameters/skip" @@ -3022,22 +3251,134 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$select", + "description": "Select properties to be returned", + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "ConfirmationCode", + "StartsAt", + "EndsAt", + "Duration" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$expand", + "description": "Expand related entities", + "type": "array", + "items": { + "enum": [ + "*" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property", + "schema": { + "title": "Collection of PlanItem", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" + } + } + } + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/NewComePeople/{UserName}/Trips/{TripId}/PlanItems/$ref": { + "get": { + "tags": [ + "NewComePeople.Trips.PlanItem" + ], + "summary": "Get ref of PlanItems from NewComePeople", + "operationId": "NewComePeople.Trips.ListRefPlanItems", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "$ref": "#/parameters/top" + }, + { + "$ref": "#/parameters/skip" + }, + { + "$ref": "#/parameters/search" + }, + { + "$ref": "#/parameters/filter" + }, + { + "$ref": "#/parameters/count" + }, + { + "in": "query", + "name": "$orderby", + "description": "Order items by property values", + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -3047,7 +3388,7 @@ "200": { "description": "Retrieved navigation property links", "schema": { - "title": "Collection of links of Trip", + "title": "Collection of links of PlanItem", "type": "object", "properties": { "value": { @@ -3067,10 +3408,10 @@ }, "post": { "tags": [ - "NewComePeople.Trip" + "NewComePeople.Trips.PlanItem" ], - "summary": "Create new navigation property ref to Trips for NewComePeople", - "operationId": "NewComePeople.CreateRefTrips", + "summary": "Create new navigation property ref to PlanItems for NewComePeople", + "operationId": "NewComePeople.Trips.CreateRefPlanItems", "consumes": [ "application/json" ], @@ -3086,6 +3427,17 @@ "type": "string", "x-ms-docs-key-type": "Person" }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, { "in": "body", "name": "body", @@ -3727,13 +4079,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Friends/{UserName1}": { + "/People/{UserName}/Friends/$ref": { "get": { "tags": [ "People.Person" ], - "summary": "Get Friends from People", - "operationId": "People.GetFriends", + "summary": "Get ref of Friends from People", + "operationId": "People.ListRefFriends", "produces": [ "application/json" ], @@ -3747,101 +4099,19 @@ "x-ms-docs-key-type": "Person" }, { - "in": "path", - "name": "UserName1", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}/Friends/$ref": { - "get": { - "tags": [ - "People.Person" - ], - "summary": "Get ref of Friends from People", - "operationId": "People.ListRefFriends", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "$ref": "#/parameters/top" - }, - { - "$ref": "#/parameters/skip" - }, - { - "$ref": "#/parameters/search" - }, - { - "$ref": "#/parameters/filter" - }, - { - "$ref": "#/parameters/count" + "$ref": "#/parameters/top" + }, + { + "$ref": "#/parameters/skip" + }, + { + "$ref": "#/parameters/search" + }, + { + "$ref": "#/parameters/filter" + }, + { + "$ref": "#/parameters/count" }, { "in": "query", @@ -4087,13 +4357,389 @@ "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.ShareTrip": { "post": { "tags": [ - "People.Actions" - ], - "summary": "Invoke action ShareTrip", - "operationId": "People.ShareTrip", - "consumes": [ - "application/json" + "People.Actions" + ], + "summary": "Invoke action ShareTrip", + "operationId": "People.ShareTrip", + "consumes": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "body", + "name": "body", + "description": "Action parameters", + "required": true, + "schema": { + "type": "object", + "properties": { + "userName": { + "type": "string" + }, + "tripId": { + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + } + } + } + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "action" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "get": { + "tags": [ + "People.Functions" + ], + "summary": "Invoke function UpdatePersonLastName", + "operationId": "People.UpdatePersonLastName", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "lastName", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "default": false, + "type": "boolean" + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "function" + } + }, + "/People/{UserName}/Trips": { + "get": { + "tags": [ + "People.Trip" + ], + "summary": "Get Trips from People", + "operationId": "People.ListTrips", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "$ref": "#/parameters/top" + }, + { + "$ref": "#/parameters/skip" + }, + { + "$ref": "#/parameters/search" + }, + { + "$ref": "#/parameters/filter" + }, + { + "$ref": "#/parameters/count" + }, + { + "in": "query", + "name": "$orderby", + "description": "Order items by property values", + "type": "array", + "items": { + "enum": [ + "TripId", + "TripId desc", + "ShareId", + "ShareId desc", + "Name", + "Name desc", + "Budget", + "Budget desc", + "Description", + "Description desc", + "Tags", + "Tags desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$select", + "description": "Select properties to be returned", + "type": "array", + "items": { + "enum": [ + "TripId", + "ShareId", + "Name", + "Budget", + "Description", + "Tags", + "StartsAt", + "EndsAt", + "PlanItems" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$expand", + "description": "Expand related entities", + "type": "array", + "items": { + "enum": [ + "*", + "PlanItems" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property", + "schema": { + "title": "Collection of Trip", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + } + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "People.Trip" + ], + "summary": "Create new navigation property to Trips for People", + "operationId": "People.CreateTrips", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + ], + "responses": { + "201": { + "description": "Created navigation property.", + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/People/{UserName}/Trips/{TripId}": { + "get": { + "tags": [ + "People.Trip" + ], + "summary": "Get Trips from People", + "operationId": "People.GetTrips", + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "query", + "name": "$select", + "description": "Select properties to be returned", + "type": "array", + "items": { + "enum": [ + "TripId", + "ShareId", + "Name", + "Budget", + "Description", + "Tags", + "StartsAt", + "EndsAt", + "PlanItems" + ], + "type": "string" + } + }, + { + "in": "query", + "name": "$expand", + "description": "Expand related entities", + "type": "array", + "items": { + "enum": [ + "*", + "PlanItems" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property", + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "patch": { + "tags": [ + "People.Trip" + ], + "summary": "Update the navigation property Trips in People", + "operationId": "People.UpdateTrips", + "consumes": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "UserName", + "description": "key: UserName of Person", + "required": true, + "type": "string", + "x-ms-docs-key-type": "Person" + }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "body", + "name": "body", + "description": "New navigation property values", + "required": true, + "schema": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "delete": { + "tags": [ + "People.Trip" ], + "summary": "Delete navigation property Trips for People", + "operationId": "People.DeleteTrips", "parameters": [ { "in": "path", @@ -4104,24 +4750,21 @@ "x-ms-docs-key-type": "Person" }, { - "in": "body", - "name": "body", - "description": "Action parameters", + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", "required": true, - "schema": { - "type": "object", - "properties": { - "userName": { - "type": "string" - }, - "tripId": { - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - } - } - } + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, + { + "in": "header", + "name": "If-Match", + "description": "ETag", + "type": "string" } ], "responses": { @@ -4132,16 +4775,16 @@ "$ref": "#/responses/error" } }, - "x-ms-docs-operation-type": "action" + "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { "get": { "tags": [ "People.Functions" ], - "summary": "Invoke function UpdatePersonLastName", - "operationId": "People.UpdatePersonLastName", + "summary": "Invoke function GetInvolvedPeople", + "operationId": "People.Trips.GetInvolvedPeople", "produces": [ "application/json" ], @@ -4156,17 +4799,24 @@ }, { "in": "path", - "name": "lastName", + "name": "TripId", + "description": "key: TripId of Trip", "required": true, - "type": "string" + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" } ], "responses": { "200": { "description": "Success", "schema": { - "default": false, - "type": "boolean" + "type": "array", + "items": { + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } } }, "default": { @@ -4176,13 +4826,13 @@ "x-ms-docs-operation-type": "function" } }, - "/People/{UserName}/Trips": { + "/People/{UserName}/Trips/{TripId}/PlanItems": { "get": { "tags": [ - "People.Trip" + "People.Trips.PlanItem" ], - "summary": "Get Trips from People", - "operationId": "People.ListTrips", + "summary": "Get PlanItems from People", + "operationId": "People.Trips.ListPlanItems", "produces": [ "application/json" ], @@ -4195,6 +4845,17 @@ "type": "string", "x-ms-docs-key-type": "Person" }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, { "$ref": "#/parameters/top" }, @@ -4217,22 +4878,16 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -4244,15 +4899,11 @@ "type": "array", "items": { "enum": [ - "TripId", - "ShareId", - "Name", - "Budget", - "Description", - "Tags", + "PlanItemId", + "ConfirmationCode", "StartsAt", "EndsAt", - "PlanItems" + "Duration" ], "type": "string" } @@ -4264,8 +4915,7 @@ "type": "array", "items": { "enum": [ - "*", - "PlanItems" + "*" ], "type": "string" } @@ -4275,13 +4925,13 @@ "200": { "description": "Retrieved navigation property", "schema": { - "title": "Collection of Trip", + "title": "Collection of PlanItem", "type": "object", "properties": { "value": { "type": "array", "items": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" } } } @@ -4294,91 +4944,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Trips/{TripId}": { - "get": { - "tags": [ - "People.Trip" - ], - "summary": "Get Trips from People", - "operationId": "People.GetTrips", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" - }, - { - "in": "path", - "name": "TripId", - "description": "key: TripId of Trip", - "required": true, - "type": "integer", - "format": "int32", - "maximum": 2147483647, - "minimum": -2147483648, - "x-ms-docs-key-type": "Trip" - }, - { - "in": "query", - "name": "$select", - "description": "Select properties to be returned", - "type": "array", - "items": { - "enum": [ - "TripId", - "ShareId", - "Name", - "Budget", - "Description", - "Tags", - "StartsAt", - "EndsAt", - "PlanItems" - ], - "type": "string" - } - }, - { - "in": "query", - "name": "$expand", - "description": "Expand related entities", - "type": "array", - "items": { - "enum": [ - "*", - "PlanItems" - ], - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "schema": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { + "/People/{UserName}/Trips/{TripId}/PlanItems/$ref": { "get": { "tags": [ - "People.Functions" + "People.Trips.PlanItem" ], - "summary": "Invoke function GetInvolvedPeople", - "operationId": "People.Trips.GetInvolvedPeople", + "summary": "Get ref of PlanItems from People", + "operationId": "People.Trips.ListRefPlanItems", "produces": [ "application/json" ], @@ -4401,43 +4973,6 @@ "maximum": 2147483647, "minimum": -2147483648, "x-ms-docs-key-type": "Trip" - } - ], - "responses": { - "200": { - "description": "Success", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } - }, - "default": { - "$ref": "#/responses/error" - } - }, - "x-ms-docs-operation-type": "function" - } - }, - "/People/{UserName}/Trips/$ref": { - "get": { - "tags": [ - "People.Trip" - ], - "summary": "Get ref of Trips from People", - "operationId": "People.ListRefTrips", - "produces": [ - "application/json" - ], - "parameters": [ - { - "in": "path", - "name": "UserName", - "description": "key: UserName of Person", - "required": true, - "type": "string", - "x-ms-docs-key-type": "Person" }, { "$ref": "#/parameters/top" @@ -4461,22 +4996,16 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -4486,7 +5015,7 @@ "200": { "description": "Retrieved navigation property links", "schema": { - "title": "Collection of links of Trip", + "title": "Collection of links of PlanItem", "type": "object", "properties": { "value": { @@ -4506,10 +5035,10 @@ }, "post": { "tags": [ - "People.Trip" + "People.Trips.PlanItem" ], - "summary": "Create new navigation property ref to Trips for People", - "operationId": "People.CreateRefTrips", + "summary": "Create new navigation property ref to PlanItems for People", + "operationId": "People.Trips.CreateRefPlanItems", "consumes": [ "application/json" ], @@ -4525,6 +5054,17 @@ "type": "string", "x-ms-docs-key-type": "Person" }, + { + "in": "path", + "name": "TripId", + "description": "key: TripId of Trip", + "required": true, + "type": "integer", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "x-ms-docs-key-type": "Trip" + }, { "in": "body", "name": "body", @@ -5250,6 +5790,10 @@ "name": "Me.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "Me.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "NewComePeople.Person", "x-ms-docs-toc-type": "page" @@ -5266,6 +5810,10 @@ "name": "NewComePeople.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "NewComePeople.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "People.Person", "x-ms-docs-toc-type": "page" @@ -5282,6 +5830,10 @@ "name": "People.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "People.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "ResetDataSource", "x-ms-docs-toc-type": "container" diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml index ef6a7284..1fb3317c 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.V2.yaml @@ -652,61 +652,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/Me/Friends/{UserName}': - get: - tags: - - Me.Person - summary: Get Friends from Me - operationId: Me.GetFriends - produces: - - application/json - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation /Me/Friends/$ref: get: tags: @@ -991,6 +936,30 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - Me.Trip + summary: Create new navigation property to Trips for Me + operationId: Me.CreateTrips + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: body + description: New navigation property + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '201': + description: Created navigation property. + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/Me/Trips/{TripId}': get: tags: @@ -1042,6 +1011,60 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - Me.Trip + summary: Update the navigation property Trips in Me + operationId: Me.UpdateTrips + consumes: + - application/json + parameters: + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: body + name: body + description: New navigation property values + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - Me.Trip + summary: Delete navigation property Trips for Me + operationId: Me.DeleteTrips + parameters: + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: header + name: If-Match + description: ETag + type: string + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/Me/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -1070,15 +1093,24 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - /Me/Trips/$ref: + '/Me/Trips/{TripId}/PlanItems': get: tags: - - Me.Trip - summary: Get ref of Trips from Me - operationId: Me.ListRefTrips + - Me.Trips.PlanItem + summary: Get PlanItems from Me + operationId: Me.Trips.ListPlanItems produces: - application/json parameters: + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - $ref: '#/parameters/top' - $ref: '#/parameters/skip' - $ref: '#/parameters/search' @@ -1090,28 +1122,96 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc + type: string + - in: query + name: $select + description: Select properties to be returned + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - in: query + name: $expand + description: Expand related entities + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + '/Me/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - Me.Trips.PlanItem + summary: Get ref of PlanItems from Me + operationId: Me.Trips.ListRefPlanItems + produces: + - application/json + parameters: + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - $ref: '#/parameters/top' + - $ref: '#/parameters/skip' + - $ref: '#/parameters/search' + - $ref: '#/parameters/filter' + - $ref: '#/parameters/count' + - in: query + name: $orderby + description: Order items by property values + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc type: string responses: '200': description: Retrieved navigation property links schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -1123,14 +1223,23 @@ paths: x-ms-docs-operation-type: operation post: tags: - - Me.Trip - summary: Create new navigation property ref to Trips for Me - operationId: Me.CreateRefTrips + - Me.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for Me + operationId: Me.Trips.CreateRefPlanItems consumes: - application/json produces: - application/json parameters: + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - in: body name: body description: New navigation property ref value @@ -1585,67 +1694,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/NewComePeople/{UserName}/Friends/{UserName1}': - get: - tags: - - NewComePeople.Person - summary: Get Friends from NewComePeople - operationId: NewComePeople.GetFriends - produces: - - application/json - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: path - name: UserName1 - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation '/NewComePeople/{UserName}/Friends/$ref': get: tags: @@ -1979,6 +2027,36 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - NewComePeople.Trip + summary: Create new navigation property to Trips for NewComePeople + operationId: NewComePeople.CreateTrips + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: body + name: body + description: New navigation property + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '201': + description: Created navigation property. + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/NewComePeople/{UserName}/Trips/{TripId}': get: tags: @@ -2036,6 +2114,72 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - NewComePeople.Trip + summary: Update the navigation property Trips in NewComePeople + operationId: NewComePeople.UpdateTrips + consumes: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: body + name: body + description: New navigation property values + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - NewComePeople.Trip + summary: Delete navigation property Trips for NewComePeople + operationId: NewComePeople.DeleteTrips + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: header + name: If-Match + description: ETag + type: string + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -2070,12 +2214,12 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - '/NewComePeople/{UserName}/Trips/$ref': + '/NewComePeople/{UserName}/Trips/{TripId}/PlanItems': get: tags: - - NewComePeople.Trip - summary: Get ref of Trips from NewComePeople - operationId: NewComePeople.ListRefTrips + - NewComePeople.Trips.PlanItem + summary: Get PlanItems from NewComePeople + operationId: NewComePeople.Trips.ListPlanItems produces: - application/json parameters: @@ -2085,6 +2229,15 @@ paths: required: true type: string x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - $ref: '#/parameters/top' - $ref: '#/parameters/skip' - $ref: '#/parameters/search' @@ -2096,28 +2249,102 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc + type: string + - in: query + name: $select + description: Select properties to be returned + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - in: query + name: $expand + description: Expand related entities + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + '/NewComePeople/{UserName}/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - NewComePeople.Trips.PlanItem + summary: Get ref of PlanItems from NewComePeople + operationId: NewComePeople.Trips.ListRefPlanItems + produces: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - $ref: '#/parameters/top' + - $ref: '#/parameters/skip' + - $ref: '#/parameters/search' + - $ref: '#/parameters/filter' + - $ref: '#/parameters/count' + - in: query + name: $orderby + description: Order items by property values + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc type: string responses: '200': description: Retrieved navigation property links schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -2129,9 +2356,9 @@ paths: x-ms-docs-operation-type: operation post: tags: - - NewComePeople.Trip - summary: Create new navigation property ref to Trips for NewComePeople - operationId: NewComePeople.CreateRefTrips + - NewComePeople.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for NewComePeople + operationId: NewComePeople.Trips.CreateRefPlanItems consumes: - application/json produces: @@ -2143,6 +2370,15 @@ paths: required: true type: string x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - in: body name: body description: New navigation property ref value @@ -2597,67 +2833,6 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation - '/People/{UserName}/Friends/{UserName1}': - get: - tags: - - People.Person - summary: Get Friends from People - operationId: People.GetFriends - produces: - - application/json - parameters: - - in: path - name: UserName - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: path - name: UserName1 - description: 'key: UserName of Person' - required: true - type: string - x-ms-docs-key-type: Person - - in: query - name: $select - description: Select properties to be returned - type: array - items: - enum: - - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - in: query - name: $expand - description: Expand related entities - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - schema: - $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/responses/error' - x-ms-docs-operation-type: operation '/People/{UserName}/Friends/$ref': get: tags: @@ -2991,6 +3166,36 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - People.Trip + summary: Create new navigation property to Trips for People + operationId: People.CreateTrips + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: body + name: body + description: New navigation property + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '201': + description: Created navigation property. + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/People/{UserName}/Trips/{TripId}': get: tags: @@ -3048,6 +3253,72 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - People.Trip + summary: Update the navigation property Trips in People + operationId: People.UpdateTrips + consumes: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: body + name: body + description: New navigation property values + required: true + schema: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - People.Trip + summary: Delete navigation property Trips for People + operationId: People.DeleteTrips + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - in: header + name: If-Match + description: ETag + type: string + responses: + '204': + description: Success + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation '/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -3082,12 +3353,12 @@ paths: default: $ref: '#/responses/error' x-ms-docs-operation-type: function - '/People/{UserName}/Trips/$ref': + '/People/{UserName}/Trips/{TripId}/PlanItems': get: tags: - - People.Trip - summary: Get ref of Trips from People - operationId: People.ListRefTrips + - People.Trips.PlanItem + summary: Get PlanItems from People + operationId: People.Trips.ListPlanItems produces: - application/json parameters: @@ -3097,6 +3368,15 @@ paths: required: true type: string x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - $ref: '#/parameters/top' - $ref: '#/parameters/skip' - $ref: '#/parameters/search' @@ -3108,28 +3388,102 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc + type: string + - in: query + name: $select + description: Select properties to be returned + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - in: query + name: $expand + description: Expand related entities + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/definitions/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/responses/error' + x-ms-docs-operation-type: operation + '/People/{UserName}/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - People.Trips.PlanItem + summary: Get ref of PlanItems from People + operationId: People.Trips.ListRefPlanItems + produces: + - application/json + parameters: + - in: path + name: UserName + description: 'key: UserName of Person' + required: true + type: string + x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip + - $ref: '#/parameters/top' + - $ref: '#/parameters/skip' + - $ref: '#/parameters/search' + - $ref: '#/parameters/filter' + - $ref: '#/parameters/count' + - in: query + name: $orderby + description: Order items by property values + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc type: string responses: '200': description: Retrieved navigation property links schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -3141,9 +3495,9 @@ paths: x-ms-docs-operation-type: operation post: tags: - - People.Trip - summary: Create new navigation property ref to Trips for People - operationId: People.CreateRefTrips + - People.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for People + operationId: People.Trips.CreateRefPlanItems consumes: - application/json produces: @@ -3155,6 +3509,15 @@ paths: required: true type: string x-ms-docs-key-type: Person + - in: path + name: TripId + description: 'key: TripId of Trip' + required: true + type: integer + format: int32 + maximum: 2147483647 + minimum: -2147483648 + x-ms-docs-key-type: Trip - in: body name: body description: New navigation property ref value @@ -3625,6 +3988,8 @@ tags: x-ms-docs-toc-type: container - name: Me.Trip x-ms-docs-toc-type: page + - name: Me.Trips.PlanItem + x-ms-docs-toc-type: page - name: NewComePeople.Person x-ms-docs-toc-type: page - name: NewComePeople.Functions @@ -3633,6 +3998,8 @@ tags: x-ms-docs-toc-type: container - name: NewComePeople.Trip x-ms-docs-toc-type: page + - name: NewComePeople.Trips.PlanItem + x-ms-docs-toc-type: page - name: People.Person x-ms-docs-toc-type: page - name: People.Functions @@ -3641,5 +4008,7 @@ tags: x-ms-docs-toc-type: container - name: People.Trip x-ms-docs-toc-type: page + - name: People.Trips.PlanItem + x-ms-docs-toc-type: page - name: ResetDataSource x-ms-docs-toc-type: container \ No newline at end of file diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json index 4928e181..9a316bc2 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.json @@ -1100,93 +1100,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/Me/Friends/{UserName}": { - "get": { - "tags": [ - "Me.Person" - ], - "summary": "Get Friends from Me", - "operationId": "Me.GetFriends", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/Me/Friends/$ref": { "get": { "tags": [ @@ -1641,6 +1554,40 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "Me.Trip" + ], + "summary": "Create new navigation property to Trips for Me", + "operationId": "Me.CreateTrips", + "requestBody": { + "description": "New navigation property", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created navigation property.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/Me/Trips/{TripId}": { @@ -1724,6 +1671,87 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "patch": { + "tags": [ + "Me.Trip" + ], + "summary": "Update the navigation property Trips in Me", + "operationId": "Me.UpdateTrips", + "parameters": [ + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + } + ], + "requestBody": { + "description": "New navigation property values", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "delete": { + "tags": [ + "Me.Trip" + ], + "summary": "Delete navigation property Trips for Me", + "operationId": "Me.DeleteTrips", + "parameters": [ + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, + { + "name": "If-Match", + "in": "header", + "description": "ETag", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/Me/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { @@ -1774,14 +1802,27 @@ "x-ms-docs-operation-type": "function" } }, - "/Me/Trips/$ref": { + "/Me/Trips/{TripId}/PlanItems": { "get": { "tags": [ - "Me.Trip" + "Me.Trips.PlanItem" ], - "summary": "Get ref of Trips from Me", - "operationId": "Me.ListRefTrips", + "summary": "Get PlanItems from Me", + "operationId": "Me.Trips.ListPlanItems", "parameters": [ + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, { "$ref": "#/components/parameters/top" }, @@ -1808,22 +1849,54 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" + ], + "type": "string" + } + } + }, + { + "name": "$select", + "in": "query", + "description": "Select properties to be returned", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "ConfirmationCode", + "StartsAt", + "EndsAt", + "Duration" + ], + "type": "string" + } + } + }, + { + "name": "$expand", + "in": "query", + "description": "Expand related entities", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "*" ], "type": "string" } @@ -1832,17 +1905,17 @@ ], "responses": { "200": { - "description": "Retrieved navigation property links", + "description": "Retrieved navigation property", "content": { "application/json": { "schema": { - "title": "Collection of links of Trip", + "title": "Collection of PlanItem", "type": "object", "properties": { "value": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" } } } @@ -1855,13 +1928,118 @@ } }, "x-ms-docs-operation-type": "operation" - }, - "post": { + } + }, + "/Me/Trips/{TripId}/PlanItems/$ref": { + "get": { "tags": [ - "Me.Trip" + "Me.Trips.PlanItem" + ], + "summary": "Get ref of PlanItems from Me", + "operationId": "Me.Trips.ListRefPlanItems", + "parameters": [ + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, + { + "$ref": "#/components/parameters/top" + }, + { + "$ref": "#/components/parameters/skip" + }, + { + "$ref": "#/components/parameters/search" + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/count" + }, + { + "name": "$orderby", + "in": "query", + "description": "Order items by property values", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc", + "Duration", + "Duration desc" + ], + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property links", + "content": { + "application/json": { + "schema": { + "title": "Collection of links of PlanItem", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "Me.Trips.PlanItem" + ], + "summary": "Create new navigation property ref to PlanItems for Me", + "operationId": "Me.Trips.CreateRefPlanItems", + "parameters": [ + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + } ], - "summary": "Create new navigation property ref to Trips for Me", - "operationId": "Me.CreateRefTrips", "requestBody": { "description": "New navigation property ref value", "content": { @@ -2579,103 +2757,6 @@ "x-ms-docs-operation-type": "operation" } }, - "/NewComePeople/{UserName}/Friends/{UserName1}": { - "get": { - "tags": [ - "NewComePeople.Person" - ], - "summary": "Get Friends from NewComePeople", - "operationId": "NewComePeople.GetFriends", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "UserName1", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, "/NewComePeople/{UserName}/Friends/$ref": { "get": { "tags": [ @@ -3218,6 +3299,52 @@ } }, "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "NewComePeople.Trip" + ], + "summary": "Create new navigation property to Trips for NewComePeople", + "operationId": "NewComePeople.CreateTrips", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "requestBody": { + "description": "New navigation property", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created navigation property.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" } }, "/NewComePeople/{UserName}/Trips/{TripId}": { @@ -3311,15 +3438,13 @@ } }, "x-ms-docs-operation-type": "operation" - } - }, - "/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { - "get": { + }, + "patch": { "tags": [ - "NewComePeople.Functions" + "NewComePeople.Trip" ], - "summary": "Invoke function GetInvolvedPeople", - "operationId": "NewComePeople.Trips.GetInvolvedPeople", + "summary": "Update the navigation property Trips in NewComePeople", + "operationId": "NewComePeople.UpdateTrips", "parameters": [ { "name": "UserName", @@ -3345,39 +3470,33 @@ "x-ms-docs-key-type": "Trip" } ], + "requestBody": { + "description": "New navigation property values", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + } + }, + "required": true + }, "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - ], - "nullable": true - } - } - } - } + "204": { + "description": "Success" }, "default": { "$ref": "#/components/responses/error" } }, - "x-ms-docs-operation-type": "function" - } - }, - "/NewComePeople/{UserName}/Trips/$ref": { - "get": { + "x-ms-docs-operation-type": "operation" + }, + "delete": { "tags": [ "NewComePeople.Trip" ], - "summary": "Get ref of Trips from NewComePeople", - "operationId": "NewComePeople.ListRefTrips", + "summary": "Delete navigation property Trips for NewComePeople", + "operationId": "NewComePeople.DeleteTrips", "parameters": [ { "name": "UserName", @@ -3390,85 +3509,45 @@ "x-ms-docs-key-type": "Person" }, { - "$ref": "#/components/parameters/top" - }, - { - "$ref": "#/components/parameters/skip" - }, - { - "$ref": "#/components/parameters/search" - }, - { - "$ref": "#/components/parameters/filter" - }, - { - "$ref": "#/components/parameters/count" + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" }, { - "name": "$orderby", - "in": "query", - "description": "Order items by property values", - "style": "form", - "explode": false, + "name": "If-Match", + "in": "header", + "description": "ETag", "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", - "StartsAt", - "StartsAt desc", - "EndsAt", - "EndsAt desc" - ], - "type": "string" - } + "type": "string" } } ], "responses": { - "200": { - "description": "Retrieved navigation property links", - "content": { - "application/json": { - "schema": { - "title": "Collection of links of Trip", - "type": "object", - "properties": { - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } + "204": { + "description": "Success" }, "default": { "$ref": "#/components/responses/error" } }, "x-ms-docs-operation-type": "operation" - }, - "post": { + } + }, + "/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { + "get": { "tags": [ - "NewComePeople.Trip" + "NewComePeople.Functions" ], - "summary": "Create new navigation property ref to Trips for NewComePeople", - "operationId": "NewComePeople.CreateRefTrips", + "summary": "Invoke function GetInvolvedPeople", + "operationId": "NewComePeople.Trips.GetInvolvedPeople", "parameters": [ { "name": "UserName", @@ -3479,29 +3558,36 @@ "type": "string" }, "x-ms-docs-key-type": "Person" + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" } ], - "requestBody": { - "description": "New navigation property ref value", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "object" - } - } - } - }, - "required": true - }, "responses": { - "201": { - "description": "Created navigation property link.", + "200": { + "description": "Success", "content": { "application/json": { "schema": { - "type": "object" + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + ], + "nullable": true + } } } } @@ -3510,17 +3596,40 @@ "$ref": "#/components/responses/error" } }, - "x-ms-docs-operation-type": "operation" + "x-ms-docs-operation-type": "function" } }, - "/People": { + "/NewComePeople/{UserName}/Trips/{TripId}/PlanItems": { "get": { "tags": [ - "People.Person" + "NewComePeople.Trips.PlanItem" ], - "summary": "Get entities from People", - "operationId": "People.Person.ListPerson", + "summary": "Get PlanItems from NewComePeople", + "operationId": "NewComePeople.Trips.ListPlanItems", "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, { "$ref": "#/components/parameters/top" }, @@ -3547,28 +3656,16 @@ "type": "array", "items": { "enum": [ - "UserName", - "UserName desc", - "FirstName", - "FirstName desc", - "LastName", - "LastName desc", - "MiddleName", - "MiddleName desc", - "Gender", - "Gender desc", - "Age", - "Age desc", - "Emails", - "Emails desc", - "AddressInfo", - "AddressInfo desc", - "HomeAddress", - "HomeAddress desc", - "FavoriteFeature", - "FavoriteFeature desc", - "Features", - "Features desc" + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -3585,20 +3682,11 @@ "type": "array", "items": { "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" + "PlanItemId", + "ConfirmationCode", + "StartsAt", + "EndsAt", + "Duration" ], "type": "string" } @@ -3615,10 +3703,7 @@ "type": "array", "items": { "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" + "*" ], "type": "string" } @@ -3627,17 +3712,17 @@ ], "responses": { "200": { - "description": "Retrieved entities", + "description": "Retrieved navigation property", "content": { "application/json": { "schema": { - "title": "Collection of Person", + "title": "Collection of PlanItem", "type": "object", "properties": { "value": { "type": "array", "items": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" } } } @@ -3648,95 +3733,60 @@ "default": { "$ref": "#/components/responses/error" } - } - }, - "post": { + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/NewComePeople/{UserName}/Trips/{TripId}/PlanItems/$ref": { + "get": { "tags": [ - "People.Person" + "NewComePeople.Trips.PlanItem" ], - "summary": "Add new entity to People", - "operationId": "People.Person.CreatePerson", - "requestBody": { - "description": "New entity", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } + "summary": "Get ref of PlanItems from NewComePeople", + "operationId": "NewComePeople.Trips.ListRefPlanItems", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" }, - "required": true - }, - "responses": { - "201": { - "description": "Created entity", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}": { - "get": { - "tags": [ - "People.Person" - ], - "summary": "Get entity from People by key", - "operationId": "People.Person.GetPerson", - "parameters": [ { - "name": "UserName", + "name": "TripId", "in": "path", - "description": "key: UserName of Person", + "description": "key: TripId of Trip", "required": true, "schema": { - "type": "string" + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" }, - "x-ms-docs-key-type": "Person" + "x-ms-docs-key-type": "Trip" }, { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } + "$ref": "#/components/parameters/top" }, { - "name": "$expand", + "$ref": "#/components/parameters/skip" + }, + { + "$ref": "#/components/parameters/search" + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/count" + }, + { + "name": "$orderby", "in": "query", - "description": "Expand related entities", + "description": "Order items by property values", "style": "form", "explode": false, "schema": { @@ -3744,10 +3794,16 @@ "type": "array", "items": { "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -3756,11 +3812,20 @@ ], "responses": { "200": { - "description": "Retrieved entity", + "description": "Retrieved navigation property links", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + "title": "Collection of links of PlanItem", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } } } } @@ -3771,12 +3836,12 @@ }, "x-ms-docs-operation-type": "operation" }, - "patch": { + "post": { "tags": [ - "People.Person" + "NewComePeople.Trips.PlanItem" ], - "summary": "Update entity in People", - "operationId": "People.Person.UpdatePerson", + "summary": "Create new navigation property ref to PlanItems for NewComePeople", + "operationId": "NewComePeople.Trips.CreateRefPlanItems", "parameters": [ { "name": "UserName", @@ -3787,58 +3852,45 @@ "type": "string" }, "x-ms-docs-key-type": "Person" + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" } ], "requestBody": { - "description": "New property values", + "description": "New navigation property ref value", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + "type": "object", + "additionalProperties": { + "type": "object" + } } } }, "required": true }, "responses": { - "204": { - "description": "Success" - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - }, - "delete": { - "tags": [ - "People.Person" - ], - "summary": "Delete entity from People", - "operationId": "People.Person.DeletePerson", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "If-Match", - "in": "header", - "description": "ETag", - "schema": { - "type": "string" + "201": { + "description": "Created navigation property link.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } } - } - ], - "responses": { - "204": { - "description": "Success" }, "default": { "$ref": "#/components/responses/error" @@ -3847,23 +3899,66 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/BestFriend": { + "/People": { "get": { "tags": [ "People.Person" ], - "summary": "Get BestFriend from People", - "operationId": "People.GetBestFriend", + "summary": "Get entities from People", + "operationId": "People.Person.ListPerson", "parameters": [ { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, + "$ref": "#/components/parameters/top" + }, + { + "$ref": "#/components/parameters/skip" + }, + { + "$ref": "#/components/parameters/search" + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/count" + }, + { + "name": "$orderby", + "in": "query", + "description": "Order items by property values", + "style": "form", + "explode": false, "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "UserName", + "UserName desc", + "FirstName", + "FirstName desc", + "LastName", + "LastName desc", + "MiddleName", + "MiddleName desc", + "Gender", + "Gender desc", + "Age", + "Age desc", + "Emails", + "Emails desc", + "AddressInfo", + "AddressInfo desc", + "HomeAddress", + "HomeAddress desc", + "FavoriteFeature", + "FavoriteFeature desc", + "Features", + "Features desc" + ], + "type": "string" + } + } }, { "name": "$select", @@ -3918,11 +4013,20 @@ ], "responses": { "200": { - "description": "Retrieved navigation property", + "description": "Retrieved entities", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + "title": "Collection of Person", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + } + } } } } @@ -3930,17 +4034,50 @@ "default": { "$ref": "#/components/responses/error" } - }, - "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}/BestFriend/$ref": { - "get": { + } + }, + "post": { "tags": [ "People.Person" ], - "summary": "Get ref of BestFriend from People", - "operationId": "People.GetRefBestFriend", + "summary": "Add new entity to People", + "operationId": "People.Person.CreatePerson", + "requestBody": { + "description": "New entity", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created entity", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/People/{UserName}": { + "get": { + "tags": [ + "People.Person" + ], + "summary": "Get entity from People by key", + "operationId": "People.Person.GetPerson", "parameters": [ { "name": "UserName", @@ -3951,15 +4088,65 @@ "type": "string" }, "x-ms-docs-key-type": "Person" + }, + { + "name": "$select", + "in": "query", + "description": "Select properties to be returned", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "UserName", + "FirstName", + "LastName", + "MiddleName", + "Gender", + "Age", + "Emails", + "AddressInfo", + "HomeAddress", + "FavoriteFeature", + "Features", + "Friends", + "BestFriend", + "Trips" + ], + "type": "string" + } + } + }, + { + "name": "$expand", + "in": "query", + "description": "Expand related entities", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "*", + "Friends", + "BestFriend", + "Trips" + ], + "type": "string" + } + } } ], "responses": { "200": { - "description": "Retrieved navigation property link", + "description": "Retrieved entity", "content": { "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" } } } @@ -3970,12 +4157,12 @@ }, "x-ms-docs-operation-type": "operation" }, - "put": { + "patch": { "tags": [ "People.Person" ], - "summary": "Update the ref of navigation property BestFriend in People", - "operationId": "People.UpdateRefBestFriend", + "summary": "Update entity in People", + "operationId": "People.Person.UpdatePerson", "parameters": [ { "name": "UserName", @@ -3989,14 +4176,11 @@ } ], "requestBody": { - "description": "New navigation property ref values", + "description": "New property values", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": { - "type": "object" - } + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" } } }, @@ -4016,8 +4200,8 @@ "tags": [ "People.Person" ], - "summary": "Delete ref of navigation property BestFriend for People", - "operationId": "People.DeleteRefBestFriend", + "summary": "Delete entity from People", + "operationId": "People.Person.DeletePerson", "parameters": [ { "name": "UserName", @@ -4049,13 +4233,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Friends": { + "/People/{UserName}/BestFriend": { "get": { "tags": [ "People.Person" ], - "summary": "Get Friends from People", - "operationId": "People.ListFriends", + "summary": "Get BestFriend from People", + "operationId": "People.GetBestFriend", "parameters": [ { "name": "UserName", @@ -4067,59 +4251,6 @@ }, "x-ms-docs-key-type": "Person" }, - { - "$ref": "#/components/parameters/top" - }, - { - "$ref": "#/components/parameters/skip" - }, - { - "$ref": "#/components/parameters/search" - }, - { - "$ref": "#/components/parameters/filter" - }, - { - "$ref": "#/components/parameters/count" - }, - { - "name": "$orderby", - "in": "query", - "description": "Order items by property values", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "UserName", - "UserName desc", - "FirstName", - "FirstName desc", - "LastName", - "LastName desc", - "MiddleName", - "MiddleName desc", - "Gender", - "Gender desc", - "Age", - "Age desc", - "Emails", - "Emails desc", - "AddressInfo", - "AddressInfo desc", - "HomeAddress", - "HomeAddress desc", - "FavoriteFeature", - "FavoriteFeature desc", - "Features", - "Features desc" - ], - "type": "string" - } - } - }, { "name": "$select", "in": "query", @@ -4177,16 +4308,7 @@ "content": { "application/json": { "schema": { - "title": "Collection of Person", - "type": "object", - "properties": { - "value": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - } - } + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" } } } @@ -4198,13 +4320,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Friends/{UserName1}": { + "/People/{UserName}/BestFriend/$ref": { "get": { "tags": [ "People.Person" ], - "summary": "Get Friends from People", - "operationId": "People.GetFriends", + "summary": "Get ref of BestFriend from People", + "operationId": "People.GetRefBestFriend", "parameters": [ { "name": "UserName", @@ -4215,75 +4337,15 @@ "type": "string" }, "x-ms-docs-key-type": "Person" - }, - { - "name": "UserName1", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "UserName", - "FirstName", - "LastName", - "MiddleName", - "Gender", - "Age", - "Emails", - "AddressInfo", - "HomeAddress", - "FavoriteFeature", - "Features", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "Friends", - "BestFriend", - "Trips" - ], - "type": "string" - } - } } ], "responses": { "200": { - "description": "Retrieved navigation property", + "description": "Retrieved navigation property link", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + "type": "string" } } } @@ -4293,15 +4355,650 @@ } }, "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}/Friends/$ref": { - "get": { + }, + "put": { "tags": [ "People.Person" ], - "summary": "Get ref of Friends from People", - "operationId": "People.ListRefFriends", + "summary": "Update the ref of navigation property BestFriend in People", + "operationId": "People.UpdateRefBestFriend", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "requestBody": { + "description": "New navigation property ref values", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object" + } + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "delete": { + "tags": [ + "People.Person" + ], + "summary": "Delete ref of navigation property BestFriend for People", + "operationId": "People.DeleteRefBestFriend", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "name": "If-Match", + "in": "header", + "description": "ETag", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/People/{UserName}/Friends": { + "get": { + "tags": [ + "People.Person" + ], + "summary": "Get Friends from People", + "operationId": "People.ListFriends", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "$ref": "#/components/parameters/top" + }, + { + "$ref": "#/components/parameters/skip" + }, + { + "$ref": "#/components/parameters/search" + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/count" + }, + { + "name": "$orderby", + "in": "query", + "description": "Order items by property values", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "UserName", + "UserName desc", + "FirstName", + "FirstName desc", + "LastName", + "LastName desc", + "MiddleName", + "MiddleName desc", + "Gender", + "Gender desc", + "Age", + "Age desc", + "Emails", + "Emails desc", + "AddressInfo", + "AddressInfo desc", + "HomeAddress", + "HomeAddress desc", + "FavoriteFeature", + "FavoriteFeature desc", + "Features", + "Features desc" + ], + "type": "string" + } + } + }, + { + "name": "$select", + "in": "query", + "description": "Select properties to be returned", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "UserName", + "FirstName", + "LastName", + "MiddleName", + "Gender", + "Age", + "Emails", + "AddressInfo", + "HomeAddress", + "FavoriteFeature", + "Features", + "Friends", + "BestFriend", + "Trips" + ], + "type": "string" + } + } + }, + { + "name": "$expand", + "in": "query", + "description": "Expand related entities", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "*", + "Friends", + "BestFriend", + "Trips" + ], + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property", + "content": { + "application/json": { + "schema": { + "title": "Collection of Person", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + } + } + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/People/{UserName}/Friends/$ref": { + "get": { + "tags": [ + "People.Person" + ], + "summary": "Get ref of Friends from People", + "operationId": "People.ListRefFriends", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "$ref": "#/components/parameters/top" + }, + { + "$ref": "#/components/parameters/skip" + }, + { + "$ref": "#/components/parameters/search" + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/count" + }, + { + "name": "$orderby", + "in": "query", + "description": "Order items by property values", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "UserName", + "UserName desc", + "FirstName", + "FirstName desc", + "LastName", + "LastName desc", + "MiddleName", + "MiddleName desc", + "Gender", + "Gender desc", + "Age", + "Age desc", + "Emails", + "Emails desc", + "AddressInfo", + "AddressInfo desc", + "HomeAddress", + "HomeAddress desc", + "FavoriteFeature", + "FavoriteFeature desc", + "Features", + "Features desc" + ], + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "Retrieved navigation property links", + "content": { + "application/json": { + "schema": { + "title": "Collection of links of Person", + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + }, + "post": { + "tags": [ + "People.Person" + ], + "summary": "Create new navigation property ref to Friends for People", + "operationId": "People.CreateRefFriends", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "requestBody": { + "description": "New navigation property ref value", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object" + } + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Created navigation property link.", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "operation" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { + "get": { + "tags": [ + "People.Functions" + ], + "summary": "Invoke function GetFavoriteAirline", + "operationId": "People.GetFavoriteAirline", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline" + } + ], + "nullable": true + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "function" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { + "get": { + "tags": [ + "People.Functions" + ], + "summary": "Invoke function GetFriendsTrips", + "operationId": "People.GetFriendsTrips", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "name": "userName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + } + ], + "nullable": true + } + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "function" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetPeersForTrip": { + "post": { + "tags": [ + "People.Actions" + ], + "summary": "Invoke action GetPeersForTrip", + "operationId": "People.GetPeersForTrip", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "requestBody": { + "description": "Action parameters", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userName": { + "type": "string" + }, + "tripId": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + } + } + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + ], + "nullable": true + } + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "action" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.ShareTrip": { + "post": { + "tags": [ + "People.Actions" + ], + "summary": "Invoke action ShareTrip", + "operationId": "People.ShareTrip", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + } + ], + "requestBody": { + "description": "Action parameters", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userName": { + "type": "string" + }, + "tripId": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + } + } + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Success" + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "action" + } + }, + "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "get": { + "tags": [ + "People.Functions" + ], + "summary": "Invoke function UpdatePersonLastName", + "operationId": "People.UpdatePersonLastName", + "parameters": [ + { + "name": "UserName", + "in": "path", + "description": "key: UserName of Person", + "required": true, + "schema": { + "type": "string" + }, + "x-ms-docs-key-type": "Person" + }, + { + "name": "lastName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "boolean", + "default": false + } + } + } + }, + "default": { + "$ref": "#/components/responses/error" + } + }, + "x-ms-docs-operation-type": "function" + } + }, + "/People/{UserName}/Trips": { + "get": { + "tags": [ + "People.Trip" + ], + "summary": "Get Trips from People", + "operationId": "People.ListTrips", "parameters": [ { "name": "UserName", @@ -4331,7 +5028,64 @@ { "name": "$orderby", "in": "query", - "description": "Order items by property values", + "description": "Order items by property values", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "TripId", + "TripId desc", + "ShareId", + "ShareId desc", + "Name", + "Name desc", + "Budget", + "Budget desc", + "Description", + "Description desc", + "Tags", + "Tags desc", + "StartsAt", + "StartsAt desc", + "EndsAt", + "EndsAt desc" + ], + "type": "string" + } + } + }, + { + "name": "$select", + "in": "query", + "description": "Select properties to be returned", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "TripId", + "ShareId", + "Name", + "Budget", + "Description", + "Tags", + "StartsAt", + "EndsAt", + "PlanItems" + ], + "type": "string" + } + } + }, + { + "name": "$expand", + "in": "query", + "description": "Expand related entities", "style": "form", "explode": false, "schema": { @@ -4339,28 +5093,8 @@ "type": "array", "items": { "enum": [ - "UserName", - "UserName desc", - "FirstName", - "FirstName desc", - "LastName", - "LastName desc", - "MiddleName", - "MiddleName desc", - "Gender", - "Gender desc", - "Age", - "Age desc", - "Emails", - "Emails desc", - "AddressInfo", - "AddressInfo desc", - "HomeAddress", - "HomeAddress desc", - "FavoriteFeature", - "FavoriteFeature desc", - "Features", - "Features desc" + "*", + "PlanItems" ], "type": "string" } @@ -4369,17 +5103,17 @@ ], "responses": { "200": { - "description": "Retrieved navigation property links", + "description": "Retrieved navigation property", "content": { "application/json": { "schema": { - "title": "Collection of links of Person", + "title": "Collection of Trip", "type": "object", "properties": { "value": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" } } } @@ -4395,10 +5129,10 @@ }, "post": { "tags": [ - "People.Person" + "People.Trip" ], - "summary": "Create new navigation property ref to Friends for People", - "operationId": "People.CreateRefFriends", + "summary": "Create new navigation property to Trips for People", + "operationId": "People.CreateTrips", "parameters": [ { "name": "UserName", @@ -4412,14 +5146,11 @@ } ], "requestBody": { - "description": "New navigation property ref value", + "description": "New navigation property", "content": { "application/json": { "schema": { - "type": "object", - "additionalProperties": { - "type": "object" - } + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" } } }, @@ -4427,11 +5158,11 @@ }, "responses": { "201": { - "description": "Created navigation property link.", + "description": "Created navigation property.", "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" } } } @@ -4443,13 +5174,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFavoriteAirline()": { + "/People/{UserName}/Trips/{TripId}": { "get": { "tags": [ - "People.Functions" + "People.Trip" ], - "summary": "Invoke function GetFavoriteAirline", - "operationId": "People.GetFavoriteAirline", + "summary": "Get Trips from People", + "operationId": "People.GetTrips", "parameters": [ { "name": "UserName", @@ -4460,73 +5191,71 @@ "type": "string" }, "x-ms-docs-key-type": "Person" - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Airline" - } - ], - "nullable": true - } - } - } }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "function" - } - }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": { - "get": { - "tags": [ - "People.Functions" - ], - "summary": "Invoke function GetFriendsTrips", - "operationId": "People.GetFriendsTrips", - "parameters": [ { - "name": "UserName", + "name": "TripId", "in": "path", - "description": "key: UserName of Person", + "description": "key: TripId of Trip", "required": true, "schema": { - "type": "string" + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" }, - "x-ms-docs-key-type": "Person" + "x-ms-docs-key-type": "Trip" }, { - "name": "userName", - "in": "path", - "required": true, + "name": "$select", + "in": "query", + "description": "Select properties to be returned", + "style": "form", + "explode": false, "schema": { - "type": "string" + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "TripId", + "ShareId", + "Name", + "Budget", + "Description", + "Tags", + "StartsAt", + "EndsAt", + "PlanItems" + ], + "type": "string" + } + } + }, + { + "name": "$expand", + "in": "query", + "description": "Expand related entities", + "style": "form", + "explode": false, + "schema": { + "uniqueItems": true, + "type": "array", + "items": { + "enum": [ + "*", + "PlanItems" + ], + "type": "string" + } } } ], "responses": { "200": { - "description": "Success", + "description": "Retrieved navigation property", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" - } - ], - "nullable": true - } + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" } } } @@ -4535,16 +5264,14 @@ "$ref": "#/components/responses/error" } }, - "x-ms-docs-operation-type": "function" - } - }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetPeersForTrip": { - "post": { + "x-ms-docs-operation-type": "operation" + }, + "patch": { "tags": [ - "People.Actions" + "People.Trip" ], - "summary": "Invoke action GetPeersForTrip", - "operationId": "People.GetPeersForTrip", + "summary": "Update the navigation property Trips in People", + "operationId": "People.UpdateTrips", "parameters": [ { "name": "UserName", @@ -4555,63 +5282,48 @@ "type": "string" }, "x-ms-docs-key-type": "Person" + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" } ], "requestBody": { - "description": "Action parameters", + "description": "New navigation property values", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "userName": { - "type": "string" - }, - "tripId": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - } - } + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" } } }, "required": true }, "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - ], - "nullable": true - } - } - } - } + "204": { + "description": "Success" }, "default": { "$ref": "#/components/responses/error" } }, - "x-ms-docs-operation-type": "action" - } - }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.ShareTrip": { - "post": { + "x-ms-docs-operation-type": "operation" + }, + "delete": { "tags": [ - "People.Actions" + "People.Trip" ], - "summary": "Invoke action ShareTrip", - "operationId": "People.ShareTrip", + "summary": "Delete navigation property Trips for People", + "operationId": "People.DeleteTrips", "parameters": [ { "name": "UserName", @@ -4622,30 +5334,29 @@ "type": "string" }, "x-ms-docs-key-type": "Person" - } - ], - "requestBody": { - "description": "Action parameters", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "userName": { - "type": "string" - }, - "tripId": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - } - } - } + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, + { + "name": "If-Match", + "in": "header", + "description": "ETag", + "schema": { + "type": "string" } - }, - "required": true - }, + } + ], "responses": { "204": { "description": "Success" @@ -4654,16 +5365,16 @@ "$ref": "#/components/responses/error" } }, - "x-ms-docs-operation-type": "action" + "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": { + "/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { "get": { "tags": [ "People.Functions" ], - "summary": "Invoke function UpdatePersonLastName", - "operationId": "People.UpdatePersonLastName", + "summary": "Invoke function GetInvolvedPeople", + "operationId": "People.Trips.GetInvolvedPeople", "parameters": [ { "name": "UserName", @@ -4676,12 +5387,17 @@ "x-ms-docs-key-type": "Person" }, { - "name": "lastName", + "name": "TripId", "in": "path", + "description": "key: TripId of Trip", "required": true, "schema": { - "type": "string" - } + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" } ], "responses": { @@ -4690,8 +5406,15 @@ "content": { "application/json": { "schema": { - "type": "boolean", - "default": false + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" + } + ], + "nullable": true + } } } } @@ -4703,13 +5426,13 @@ "x-ms-docs-operation-type": "function" } }, - "/People/{UserName}/Trips": { + "/People/{UserName}/Trips/{TripId}/PlanItems": { "get": { "tags": [ - "People.Trip" + "People.Trips.PlanItem" ], - "summary": "Get Trips from People", - "operationId": "People.ListTrips", + "summary": "Get PlanItems from People", + "operationId": "People.Trips.ListPlanItems", "parameters": [ { "name": "UserName", @@ -4721,6 +5444,19 @@ }, "x-ms-docs-key-type": "Person" }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" + }, { "$ref": "#/components/parameters/top" }, @@ -4747,22 +5483,16 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -4779,15 +5509,11 @@ "type": "array", "items": { "enum": [ - "TripId", - "ShareId", - "Name", - "Budget", - "Description", - "Tags", + "PlanItemId", + "ConfirmationCode", "StartsAt", "EndsAt", - "PlanItems" + "Duration" ], "type": "string" } @@ -4804,8 +5530,7 @@ "type": "array", "items": { "enum": [ - "*", - "PlanItems" + "*" ], "type": "string" } @@ -4818,13 +5543,13 @@ "content": { "application/json": { "schema": { - "title": "Collection of Trip", + "title": "Collection of PlanItem", "type": "object", "properties": { "value": { "type": "array", "items": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" + "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem" } } } @@ -4839,106 +5564,13 @@ "x-ms-docs-operation-type": "operation" } }, - "/People/{UserName}/Trips/{TripId}": { - "get": { - "tags": [ - "People.Trip" - ], - "summary": "Get Trips from People", - "operationId": "People.GetTrips", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" - }, - { - "name": "TripId", - "in": "path", - "description": "key: TripId of Trip", - "required": true, - "schema": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer", - "format": "int32" - }, - "x-ms-docs-key-type": "Trip" - }, - { - "name": "$select", - "in": "query", - "description": "Select properties to be returned", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "TripId", - "ShareId", - "Name", - "Budget", - "Description", - "Tags", - "StartsAt", - "EndsAt", - "PlanItems" - ], - "type": "string" - } - } - }, - { - "name": "$expand", - "in": "query", - "description": "Expand related entities", - "style": "form", - "explode": false, - "schema": { - "uniqueItems": true, - "type": "array", - "items": { - "enum": [ - "*", - "PlanItems" - ], - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "Retrieved navigation property", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip" - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "operation" - } - }, - "/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()": { + "/People/{UserName}/Trips/{TripId}/PlanItems/$ref": { "get": { "tags": [ - "People.Functions" + "People.Trips.PlanItem" ], - "summary": "Invoke function GetInvolvedPeople", - "operationId": "People.Trips.GetInvolvedPeople", + "summary": "Get ref of PlanItems from People", + "operationId": "People.Trips.ListRefPlanItems", "parameters": [ { "name": "UserName", @@ -4962,51 +5594,6 @@ "format": "int32" }, "x-ms-docs-key-type": "Trip" - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person" - } - ], - "nullable": true - } - } - } - } - }, - "default": { - "$ref": "#/components/responses/error" - } - }, - "x-ms-docs-operation-type": "function" - } - }, - "/People/{UserName}/Trips/$ref": { - "get": { - "tags": [ - "People.Trip" - ], - "summary": "Get ref of Trips from People", - "operationId": "People.ListRefTrips", - "parameters": [ - { - "name": "UserName", - "in": "path", - "description": "key: UserName of Person", - "required": true, - "schema": { - "type": "string" - }, - "x-ms-docs-key-type": "Person" }, { "$ref": "#/components/parameters/top" @@ -5034,22 +5621,16 @@ "type": "array", "items": { "enum": [ - "TripId", - "TripId desc", - "ShareId", - "ShareId desc", - "Name", - "Name desc", - "Budget", - "Budget desc", - "Description", - "Description desc", - "Tags", - "Tags desc", + "PlanItemId", + "PlanItemId desc", + "ConfirmationCode", + "ConfirmationCode desc", "StartsAt", "StartsAt desc", "EndsAt", - "EndsAt desc" + "EndsAt desc", + "Duration", + "Duration desc" ], "type": "string" } @@ -5062,7 +5643,7 @@ "content": { "application/json": { "schema": { - "title": "Collection of links of Trip", + "title": "Collection of links of PlanItem", "type": "object", "properties": { "value": { @@ -5084,10 +5665,10 @@ }, "post": { "tags": [ - "People.Trip" + "People.Trips.PlanItem" ], - "summary": "Create new navigation property ref to Trips for People", - "operationId": "People.CreateRefTrips", + "summary": "Create new navigation property ref to PlanItems for People", + "operationId": "People.Trips.CreateRefPlanItems", "parameters": [ { "name": "UserName", @@ -5098,6 +5679,19 @@ "type": "string" }, "x-ms-docs-key-type": "Person" + }, + { + "name": "TripId", + "in": "path", + "description": "key: TripId of Trip", + "required": true, + "schema": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer", + "format": "int32" + }, + "x-ms-docs-key-type": "Trip" } ], "requestBody": { @@ -6155,6 +6749,10 @@ "name": "Me.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "Me.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "NewComePeople.Person", "x-ms-docs-toc-type": "page" @@ -6171,6 +6769,10 @@ "name": "NewComePeople.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "NewComePeople.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "People.Person", "x-ms-docs-toc-type": "page" @@ -6187,6 +6789,10 @@ "name": "People.Trip", "x-ms-docs-toc-type": "page" }, + { + "name": "People.Trips.PlanItem", + "x-ms-docs-toc-type": "page" + }, { "name": "ResetDataSource", "x-ms-docs-toc-type": "container" diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml index 4108eb61..ad73cb2a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Resources/TripService.OpenApi.yaml @@ -737,70 +737,6 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - '/Me/Friends/{UserName}': - get: - tags: - - Me.Person - summary: Get Friends from Me - operationId: Me.GetFriends - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: $select - in: query - description: Select properties to be returned - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation /Me/Friends/$ref: get: tags: @@ -1103,6 +1039,28 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - Me.Trip + summary: Create new navigation property to Trips for Me + operationId: Me.CreateTrips + requestBody: + description: New navigation property + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '201': + description: Created navigation property. + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/Me/Trips/{TripId}': get: tags: @@ -1163,6 +1121,62 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - Me.Trip + summary: Update the navigation property Trips in Me + operationId: Me.UpdateTrips + parameters: + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + requestBody: + description: New navigation property values + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - Me.Trip + summary: Delete navigation property Trips for Me + operationId: Me.DeleteTrips + parameters: + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - name: If-Match + in: header + description: ETag + schema: + type: string + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/Me/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -1194,13 +1208,23 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - /Me/Trips/$ref: + '/Me/Trips/{TripId}/PlanItems': get: tags: - - Me.Trip - summary: Get ref of Trips from Me - operationId: Me.ListRefTrips + - Me.Trips.PlanItem + summary: Get PlanItems from Me + operationId: Me.Trips.ListPlanItems parameters: + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip - $ref: '#/components/parameters/top' - $ref: '#/components/parameters/skip' - $ref: '#/components/parameters/search' @@ -1216,22 +1240,103 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc + type: string + - name: $select + in: query + description: Select properties to be returned + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - name: $expand + in: query + description: Expand related entities + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + content: + application/json: + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + '/Me/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - Me.Trips.PlanItem + summary: Get ref of PlanItems from Me + operationId: Me.Trips.ListRefPlanItems + parameters: + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - $ref: '#/components/parameters/top' + - $ref: '#/components/parameters/skip' + - $ref: '#/components/parameters/search' + - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/count' + - name: $orderby + in: query + description: Order items by property values + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc type: string responses: '200': @@ -1239,7 +1344,7 @@ paths: content: application/json: schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -1251,9 +1356,20 @@ paths: x-ms-docs-operation-type: operation post: tags: - - Me.Trip - summary: Create new navigation property ref to Trips for Me - operationId: Me.CreateRefTrips + - Me.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for Me + operationId: Me.Trips.CreateRefPlanItems + parameters: + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip requestBody: description: New navigation property ref value content: @@ -1757,12 +1873,12 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation - '/NewComePeople/{UserName}/Friends/{UserName1}': + '/NewComePeople/{UserName}/Friends/$ref': get: tags: - NewComePeople.Person - summary: Get Friends from NewComePeople - operationId: NewComePeople.GetFriends + summary: Get ref of Friends from NewComePeople + operationId: NewComePeople.ListRefFriends parameters: - name: UserName in: path @@ -1771,16 +1887,14 @@ paths: schema: type: string x-ms-docs-key-type: Person - - name: UserName1 - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - name: $select + - $ref: '#/components/parameters/top' + - $ref: '#/components/parameters/skip' + - $ref: '#/components/parameters/search' + - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/count' + - name: $orderby in: query - description: Select properties to be returned + description: Order items by property values style: form explode: false schema: @@ -1789,76 +1903,7 @@ paths: items: enum: - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - '/NewComePeople/{UserName}/Friends/$ref': - get: - tags: - - NewComePeople.Person - summary: Get ref of Friends from NewComePeople - operationId: NewComePeople.ListRefFriends - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - $ref: '#/components/parameters/top' - - $ref: '#/components/parameters/skip' - - $ref: '#/components/parameters/search' - - $ref: '#/components/parameters/filter' - - $ref: '#/components/parameters/count' - - name: $orderby - in: query - description: Order items by property values - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - UserName - - UserName desc + - UserName desc - FirstName - FirstName desc - LastName @@ -2190,6 +2235,36 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - NewComePeople.Trip + summary: Create new navigation property to Trips for NewComePeople + operationId: NewComePeople.CreateTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + requestBody: + description: New navigation property + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '201': + description: Created navigation property. + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/NewComePeople/{UserName}/Trips/{TripId}': get: tags: @@ -2257,6 +2332,76 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - NewComePeople.Trip + summary: Update the navigation property Trips in NewComePeople + operationId: NewComePeople.UpdateTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + requestBody: + description: New navigation property values + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - NewComePeople.Trip + summary: Delete navigation property Trips for NewComePeople + operationId: NewComePeople.DeleteTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - name: If-Match + in: header + description: ETag + schema: + type: string + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/NewComePeople/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -2295,12 +2440,12 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - '/NewComePeople/{UserName}/Trips/$ref': + '/NewComePeople/{UserName}/Trips/{TripId}/PlanItems': get: tags: - - NewComePeople.Trip - summary: Get ref of Trips from NewComePeople - operationId: NewComePeople.ListRefTrips + - NewComePeople.Trips.PlanItem + summary: Get PlanItems from NewComePeople + operationId: NewComePeople.Trips.ListPlanItems parameters: - name: UserName in: path @@ -2309,6 +2454,16 @@ paths: schema: type: string x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip - $ref: '#/components/parameters/top' - $ref: '#/components/parameters/skip' - $ref: '#/components/parameters/search' @@ -2324,22 +2479,110 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc + type: string + - name: $select + in: query + description: Select properties to be returned + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - name: $expand + in: query + description: Expand related entities + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + content: + application/json: + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + '/NewComePeople/{UserName}/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - NewComePeople.Trips.PlanItem + summary: Get ref of PlanItems from NewComePeople + operationId: NewComePeople.Trips.ListRefPlanItems + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - $ref: '#/components/parameters/top' + - $ref: '#/components/parameters/skip' + - $ref: '#/components/parameters/search' + - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/count' + - name: $orderby + in: query + description: Order items by property values + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc type: string responses: '200': @@ -2347,7 +2590,7 @@ paths: content: application/json: schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -2359,9 +2602,9 @@ paths: x-ms-docs-operation-type: operation post: tags: - - NewComePeople.Trip - summary: Create new navigation property ref to Trips for NewComePeople - operationId: NewComePeople.CreateRefTrips + - NewComePeople.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for NewComePeople + operationId: NewComePeople.Trips.CreateRefPlanItems parameters: - name: UserName in: path @@ -2370,6 +2613,16 @@ paths: schema: type: string x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip requestBody: description: New navigation property ref value content: @@ -2770,115 +3023,7 @@ paths: tags: - People.Person summary: Get Friends from People - operationId: People.ListFriends - parameters: - - name: UserName - in: path - description: 'key: UserName of Person' - required: true - schema: - type: string - x-ms-docs-key-type: Person - - $ref: '#/components/parameters/top' - - $ref: '#/components/parameters/skip' - - $ref: '#/components/parameters/search' - - $ref: '#/components/parameters/filter' - - $ref: '#/components/parameters/count' - - name: $orderby - in: query - description: Order items by property values - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - UserName - - UserName desc - - FirstName - - FirstName desc - - LastName - - LastName desc - - MiddleName - - MiddleName desc - - Gender - - Gender desc - - Age - - Age desc - - Emails - - Emails desc - - AddressInfo - - AddressInfo desc - - HomeAddress - - HomeAddress desc - - FavoriteFeature - - FavoriteFeature desc - - Features - - Features desc - type: string - - name: $select - in: query - description: Select properties to be returned - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - UserName - - FirstName - - LastName - - MiddleName - - Gender - - Age - - Emails - - AddressInfo - - HomeAddress - - FavoriteFeature - - Features - - Friends - - BestFriend - - Trips - type: string - - name: $expand - in: query - description: Expand related entities - style: form - explode: false - schema: - uniqueItems: true - type: array - items: - enum: - - '*' - - Friends - - BestFriend - - Trips - type: string - responses: - '200': - description: Retrieved navigation property - content: - application/json: - schema: - title: Collection of Person - type: object - properties: - value: - type: array - items: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' - default: - $ref: '#/components/responses/error' - x-ms-docs-operation-type: operation - '/People/{UserName}/Friends/{UserName1}': - get: - tags: - - People.Person - summary: Get Friends from People - operationId: People.GetFriends + operationId: People.ListFriends parameters: - name: UserName in: path @@ -2887,13 +3032,44 @@ paths: schema: type: string x-ms-docs-key-type: Person - - name: UserName1 - in: path - description: 'key: UserName of Person' - required: true + - $ref: '#/components/parameters/top' + - $ref: '#/components/parameters/skip' + - $ref: '#/components/parameters/search' + - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/count' + - name: $orderby + in: query + description: Order items by property values + style: form + explode: false schema: - type: string - x-ms-docs-key-type: Person + uniqueItems: true + type: array + items: + enum: + - UserName + - UserName desc + - FirstName + - FirstName desc + - LastName + - LastName desc + - MiddleName + - MiddleName desc + - Gender + - Gender desc + - Age + - Age desc + - Emails + - Emails desc + - AddressInfo + - AddressInfo desc + - HomeAddress + - HomeAddress desc + - FavoriteFeature + - FavoriteFeature desc + - Features + - Features desc + type: string - name: $select in: query description: Select properties to be returned @@ -2940,7 +3116,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' + title: Collection of Person + type: object + properties: + value: + type: array + items: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person' default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation @@ -3306,6 +3488,36 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + post: + tags: + - People.Trip + summary: Create new navigation property to Trips for People + operationId: People.CreateTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + requestBody: + description: New navigation property + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '201': + description: Created navigation property. + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/People/{UserName}/Trips/{TripId}': get: tags: @@ -3373,6 +3585,76 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: operation + patch: + tags: + - People.Trip + summary: Update the navigation property Trips in People + operationId: People.UpdateTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + requestBody: + description: New navigation property values + content: + application/json: + schema: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Trip' + required: true + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + delete: + tags: + - People.Trip + summary: Delete navigation property Trips for People + operationId: People.DeleteTrips + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - name: If-Match + in: header + description: ETag + schema: + type: string + responses: + '204': + description: Success + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation '/People/{UserName}/Trips/{TripId}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetInvolvedPeople()': get: tags: @@ -3411,12 +3693,12 @@ paths: default: $ref: '#/components/responses/error' x-ms-docs-operation-type: function - '/People/{UserName}/Trips/$ref': + '/People/{UserName}/Trips/{TripId}/PlanItems': get: tags: - - People.Trip - summary: Get ref of Trips from People - operationId: People.ListRefTrips + - People.Trips.PlanItem + summary: Get PlanItems from People + operationId: People.Trips.ListPlanItems parameters: - name: UserName in: path @@ -3425,6 +3707,16 @@ paths: schema: type: string x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip - $ref: '#/components/parameters/top' - $ref: '#/components/parameters/skip' - $ref: '#/components/parameters/search' @@ -3440,22 +3732,110 @@ paths: type: array items: enum: - - TripId - - TripId desc - - ShareId - - ShareId desc - - Name - - Name desc - - Budget - - Budget desc - - Description - - Description desc - - Tags - - Tags desc + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc + - StartsAt + - StartsAt desc + - EndsAt + - EndsAt desc + - Duration + - Duration desc + type: string + - name: $select + in: query + description: Select properties to be returned + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - ConfirmationCode + - StartsAt + - EndsAt + - Duration + type: string + - name: $expand + in: query + description: Expand related entities + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - '*' + type: string + responses: + '200': + description: Retrieved navigation property + content: + application/json: + schema: + title: Collection of PlanItem + type: object + properties: + value: + type: array + items: + $ref: '#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.PlanItem' + default: + $ref: '#/components/responses/error' + x-ms-docs-operation-type: operation + '/People/{UserName}/Trips/{TripId}/PlanItems/$ref': + get: + tags: + - People.Trips.PlanItem + summary: Get ref of PlanItems from People + operationId: People.Trips.ListRefPlanItems + parameters: + - name: UserName + in: path + description: 'key: UserName of Person' + required: true + schema: + type: string + x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip + - $ref: '#/components/parameters/top' + - $ref: '#/components/parameters/skip' + - $ref: '#/components/parameters/search' + - $ref: '#/components/parameters/filter' + - $ref: '#/components/parameters/count' + - name: $orderby + in: query + description: Order items by property values + style: form + explode: false + schema: + uniqueItems: true + type: array + items: + enum: + - PlanItemId + - PlanItemId desc + - ConfirmationCode + - ConfirmationCode desc - StartsAt - StartsAt desc - EndsAt - EndsAt desc + - Duration + - Duration desc type: string responses: '200': @@ -3463,7 +3843,7 @@ paths: content: application/json: schema: - title: Collection of links of Trip + title: Collection of links of PlanItem type: object properties: value: @@ -3475,9 +3855,9 @@ paths: x-ms-docs-operation-type: operation post: tags: - - People.Trip - summary: Create new navigation property ref to Trips for People - operationId: People.CreateRefTrips + - People.Trips.PlanItem + summary: Create new navigation property ref to PlanItems for People + operationId: People.Trips.CreateRefPlanItems parameters: - name: UserName in: path @@ -3486,6 +3866,16 @@ paths: schema: type: string x-ms-docs-key-type: Person + - name: TripId + in: path + description: 'key: TripId of Trip' + required: true + schema: + maximum: 2147483647 + minimum: -2147483648 + type: integer + format: int32 + x-ms-docs-key-type: Trip requestBody: description: New navigation property ref value content: @@ -4136,6 +4526,8 @@ tags: x-ms-docs-toc-type: container - name: Me.Trip x-ms-docs-toc-type: page + - name: Me.Trips.PlanItem + x-ms-docs-toc-type: page - name: NewComePeople.Person x-ms-docs-toc-type: page - name: NewComePeople.Functions @@ -4144,6 +4536,8 @@ tags: x-ms-docs-toc-type: container - name: NewComePeople.Trip x-ms-docs-toc-type: page + - name: NewComePeople.Trips.PlanItem + x-ms-docs-toc-type: page - name: People.Person x-ms-docs-toc-type: page - name: People.Functions @@ -4152,5 +4546,7 @@ tags: x-ms-docs-toc-type: container - name: People.Trip x-ms-docs-toc-type: page + - name: People.Trips.PlanItem + x-ms-docs-toc-type: page - name: ResetDataSource x-ms-docs-toc-type: container \ No newline at end of file From 7fa737c6803697f8b0bb637406776bd54233af9c Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Mon, 14 Sep 2020 19:21:01 +0300 Subject: [PATCH 08/12] Fix: Generates stream paths for navigation properties (#7) * Generate stream paths for navigation properties * Refactor out stream path generation into separate function * Create base class for media entity operations handler * Add new stream segments conditional checks when creating a NavPropPath * Add Get and Put operation ids for single-valued nav. prop. paths * Update handler with support for both Entityset/Singleton stream paths * Update tests to validate the stream paths updates * Revert removed modifier * Remove unnecessary schema definition * Add application/json content in RequestBody * Nitpick: format code Co-authored-by: Irvine Sunday --- .../Edm/ODataPathProvider.cs | 63 ++++++---- .../MediaEntityGetOperationHandler.cs | 51 ++++---- .../MediaEntityOperationalHandler.cs | 114 ++++++++++++++++++ .../MediaEntityPutOperationHandler.cs | 46 +++++-- .../NavigationPropertyOperationHandler.cs | 5 +- .../PathItem/MediaEntityPathItemHandler.cs | 38 +++++- .../Edm/ODataPathProviderTests.cs | 30 +++-- .../MediaEntityGetOperationHandlerTests.cs | 34 +++++- .../MediaEntityPutOperationHandlerTests.cs | 19 +++ .../MediaEntityPathItemHandlerTests.cs | 58 +++++++-- 10 files changed, 377 insertions(+), 81 deletions(-) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs index 18c1791e..49ff1ef9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataPathProvider.cs @@ -184,14 +184,44 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource } // media entity + RetrieveMediaEntityStreamPaths(entityType, path); + + // navigation property + foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) + { + if (CanFilter(np)) + { + RetrieveNavigationPropertyPaths(np, path); + } + } + + if (entitySet != null) + { + path.Pop(); // end of entity + } + + path.Pop(); // end of navigation source. + Debug.Assert(path.Any() == false); + } + + /// + /// Retrieves the paths for a media entity stream. + /// + /// The entity type. + /// The current OData path. + private void RetrieveMediaEntityStreamPaths(IEdmEntityType entityType, ODataPath currentPath) + { + Debug.Assert(entityType != null); + Debug.Assert(currentPath != null); + bool createValuePath = true; foreach (IEdmStructuralProperty sp in entityType.DeclaredStructuralProperties()) { if (sp.Type.AsPrimitive().IsStream()) { - path.Push(new ODataStreamPropertySegment(sp.Name)); - AppendPath(path.Clone()); - path.Pop(); + currentPath.Push(new ODataStreamPropertySegment(sp.Name)); + AppendPath(currentPath.Clone()); + currentPath.Pop(); } if (sp.Name.Equals("content", System.StringComparison.OrdinalIgnoreCase)) @@ -205,27 +235,10 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource */ if (createValuePath && entityType.HasStream) { - path.Push(new ODataStreamContentSegment()); - AppendPath(path.Clone()); - path.Pop(); + currentPath.Push(new ODataStreamContentSegment()); + AppendPath(currentPath.Clone()); + currentPath.Pop(); } - - // navigation property - foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) - { - if (CanFilter(np)) - { - RetrieveNavigationPropertyPaths(np, path); - } - } - - if (entitySet != null) - { - path.Pop(); // end of entity - } - - path.Pop(); // end of navigation source. - Debug.Assert(path.Any() == false); } /// @@ -284,6 +297,10 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr } } } + + // Get possible navigation property stream paths + RetrieveMediaEntityStreamPaths(navEntityType, currentPath); + if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { currentPath.Pop(); diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs index fa6cf701..d0c8fa41 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs @@ -17,7 +17,7 @@ namespace Microsoft.OpenApi.OData.Operation /// /// Retrieve a media content for an Entity /// - internal class MediaEntityGetOperationHandler : EntitySetOperationHandler + internal class MediaEntityGetOperationHandler : MediaEntityOperationalHandler { /// public override OperationType OperationType => OperationType.Get; @@ -25,16 +25,31 @@ internal class MediaEntityGetOperationHandler : EntitySetOperationHandler /// protected override void SetBasicInfo(OpenApiOperation operation) { - string typeName = EntitySet.EntityType().Name; - // Summary - operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}"; + if (EntitySet != null) + { + string typeName = EntitySet.EntityType().Name; + operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}"; + } + else + { + operation.Summary = $"Get media content for the navigation property {NavigationProperty.Name} from {NavigationSource.Name}"; + } // OperationId if (Context.Settings.EnableOperationId) { string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; - operation.OperationId = EntitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(identifier); + + if (EntitySet != null) + { + string typeName = EntitySet.EntityType().Name; + operation.OperationId = $"{EntitySet.Name}.{typeName}.Get{Utils.UpperFirstChar(identifier)}"; + } + else // Singleton + { + operation.OperationId = GetOperationId("Get", identifier); + } } base.SetBasicInfo(operation); @@ -43,22 +58,6 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForResponses) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - Type = "string", - Format = "binary" - }; - } - operation.Responses = new OpenApiResponses { { @@ -72,7 +71,11 @@ protected override void SetResponses(OpenApiOperation operation) Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType { - Schema = schema + Schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + } } } } @@ -86,7 +89,9 @@ protected override void SetResponses(OpenApiOperation operation) /// protected override void SetSecurity(OpenApiOperation operation) { - ReadRestrictionsType read = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + ReadRestrictionsType read = EntitySet != null + ? Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions) + : Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions); if (read == null) { return; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs new file mode 100644 index 00000000..e1c7afdd --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs @@ -0,0 +1,114 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using Microsoft.OData.Edm; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.OpenApi.OData.Operation +{ + /// + /// Base class for operation of media entity. + /// + internal abstract class MediaEntityOperationalHandler : NavigationPropertyOperationHandler + { + /// + /// Gets/sets the . + /// + protected IEdmEntitySet EntitySet { get; private set; } + + /// + /// Gets the . + /// + protected IEdmSingleton Singleton { get; private set; } + + /// + protected override void Initialize(ODataContext context, ODataPath path) + { + // The first segment will either be an entity set navigation source or a singleton navigation source. + ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; + EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet; + + if (EntitySet == null) + { + // Singleton + base.Initialize(context, path); + Singleton = NavigationSource as IEdmSingleton; + } + } + + /// + protected override void SetTags(OpenApiOperation operation) + { + if (EntitySet == null) + { + // Singleton + base.SetTags(operation); + } + else // Entityset + { + string tagIdentifier = EntitySet.Name + "." + EntitySet.EntityType().Name; + + OpenApiTag tag = new OpenApiTag + { + 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); + } + } + + /// + protected override void SetExtensions(OpenApiOperation operation) + { + base.SetExtensions(operation); + } + + /// + /// Retrieves the operation Id for a navigation property stream path. + /// + /// The http method identifier name. + /// The stream segment identifier name. + /// + protected string GetOperationId(string prefix, string identifier) + { + Utils.CheckArgumentNull(prefix, nameof(prefix)); + Utils.CheckArgumentNull(identifier, nameof(identifier)); + + IList items = new List + { + NavigationSource.Name + }; + + var lastpath = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment); + foreach (var segment in Path.Segments.Skip(1)) + { + if (segment == lastpath) + { + items.Add(prefix + Utils.UpperFirstChar(identifier)); + break; + } + else + { + if (segment is ODataNavigationPropertySegment npSegment) + { + items.Add(npSegment.NavigationProperty.Name); + } + } + } + + return string.Join(".", items); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs index a8ca7cf9..a6a33a68 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs @@ -17,7 +17,7 @@ namespace Microsoft.OpenApi.OData.Operation /// /// Update a media content for an Entity /// - internal class MediaEntityPutOperationHandler : EntitySetOperationHandler + internal class MediaEntityPutOperationHandler : MediaEntityOperationalHandler { /// public override OperationType OperationType => OperationType.Put; @@ -25,16 +25,31 @@ internal class MediaEntityPutOperationHandler : EntitySetOperationHandler /// protected override void SetBasicInfo(OpenApiOperation operation) { - string typeName = EntitySet.EntityType().Name; - // Summary - operation.Summary = $"Update media content for {typeName} in {EntitySet.Name}"; + if (EntitySet != null) + { + string typeName = EntitySet.EntityType().Name; + operation.Summary = $"Update media content for {typeName} in {EntitySet.Name}"; + } + else + { + operation.Summary = $"Update media content for the navigation property {NavigationProperty.Name} in {NavigationSource.Name}"; + } // OperationId if (Context.Settings.EnableOperationId) { string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; - operation.OperationId = EntitySet.Name + "." + typeName + ".Update" + Utils.UpperFirstChar(identifier); + + if (EntitySet != null) + { + string typeName = EntitySet.EntityType().Name; + operation.OperationId = $"{EntitySet.Name}.{typeName}.Update{Utils.UpperFirstChar(identifier)}"; + } + else + { + operation.OperationId = GetOperationId("Update", identifier); + } } base.SetBasicInfo(operation); @@ -54,8 +69,11 @@ protected override void SetRequestBody(OpenApiOperation operation) { schema = new OpenApiSchema { - Type = "string", - Format = "binary" + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = EntitySet != null ? EntitySet.EntityType().FullName() : Singleton.EntityType().FullName() + } }; } @@ -67,6 +85,16 @@ protected override void SetRequestBody(OpenApiOperation operation) { { Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + } + } + }, + { + Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = schema } @@ -92,7 +120,9 @@ protected override void SetResponses(OpenApiOperation operation) /// protected override void SetSecurity(OpenApiOperation operation) { - UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); + UpdateRestrictionsType update = EntitySet != null + ? Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions) + : Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions); if (update == null || update.Permissions == null) { return; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs index dab1643f..c183fa26 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/NavigationPropertyOperationHandler.cs @@ -62,7 +62,8 @@ protected override void Initialize(ODataContext context, ODataPath path) NavigationProperty = path.OfType().Last().NavigationProperty; NavigationPropertyPath = string.Join("/", - Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment)).Select(e => e.Identifier)); + Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment + || s is ODataStreamContentSegment || s is ODataStreamPropertySegment)).Select(e => e.Identifier)); IEdmEntitySet entitySet = NavigationSource as IEdmEntitySet; IEdmSingleton singleton = NavigationSource as IEdmSingleton; @@ -115,7 +116,7 @@ protected override void SetTags(OpenApiOperation operation) } } } - + string name = string.Join(".", items); OpenApiTag tag = new OpenApiTag { diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs index 24d75c5c..d7ec6c34 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/MediaEntityPathItemHandler.cs @@ -3,6 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Vocabulary.Capabilities; @@ -12,15 +13,28 @@ namespace Microsoft.OpenApi.OData.PathItem /// /// Create a for a media entity. /// - internal class MediaEntityPathItemHandler : EntitySetPathItemHandler + internal class MediaEntityPathItemHandler : PathItemHandler { /// protected override ODataPathKind HandleKind => ODataPathKind.MediaEntity; + /// + /// Gets the entity set. + /// + protected IEdmEntitySet EntitySet { get; private set; } + + /// + /// Gets the singleton. + /// + protected IEdmSingleton Singleton { get; private set; } + /// protected override void SetOperations(OpenApiPathItem item) { - ReadRestrictionsType read = Context.Model.GetRecord(EntitySet); + ReadRestrictionsType read = EntitySet != null + ? Context.Model.GetRecord(EntitySet) + : Context.Model.GetRecord(Singleton); + if (read == null || (read.ReadByKeyRestrictions == null && read.IsReadable) || (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.IsReadable)) @@ -28,11 +42,29 @@ protected override void SetOperations(OpenApiPathItem item) AddOperation(item, OperationType.Get); } - UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet); + UpdateRestrictionsType update = EntitySet != null + ? Context.Model.GetRecord(EntitySet) + : Context.Model.GetRecord(Singleton); + if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Put); } } + + /// + protected override void Initialize(ODataContext context, ODataPath path) + { + base.Initialize(context, path); + + // The first segment could be an entity set segment or a singleton segment. + ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; + + EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet; + if (EntitySet == null) + { + Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton; + } + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs index a740a7d9..e189e94a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/ODataPathProviderTests.cs @@ -44,7 +44,7 @@ public void GetPathsForGraphBetaModelReturnsAllPaths() // Assert Assert.NotNull(paths); - Assert.Equal(4457, paths.Count()); + Assert.Equal(4544, paths.Count()); } [Fact] @@ -192,7 +192,7 @@ public void GetPathsWithContainedNavigationPropertytWorks() "; - + string entitySet = @""; IEdmModel model = GetEdmModel(entityType, entitySet); ODataPathProvider provider = new ODataPathProvider(); @@ -229,21 +229,21 @@ public void GetPathsWithStreamPropertyAndWithEntityHasStreamWorks(bool hasStream if (hasStream && !streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase)) { - Assert.Equal(4, paths.Count()); - Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/$value", "/Todos({Id})/Logo" }, + Assert.Equal(7, paths.Count()); + Assert.Equal(new[] { "/me", "/me/photo", "/me/photo/$value", "/Todos", "/Todos({Id})", "/Todos({Id})/$value", "/Todos({Id})/Logo" }, paths.Select(p => p.GetPathItemName())); } else if ((hasStream && streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase)) || (!hasStream && streamPropName.Equals("Content", StringComparison.OrdinalIgnoreCase))) { - Assert.Equal(3, paths.Count()); - Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/Content" }, + Assert.Equal(6, paths.Count()); + Assert.Equal(new[] { "/me", "/me/photo", "/me/photo/$value", "/Todos", "/Todos({Id})", "/Todos({Id})/Content" }, paths.Select(p => p.GetPathItemName())); } else // !hasStream && !streamPropName.Equals("Content") { - Assert.Equal(3, paths.Count()); - Assert.Equal(new[] { "/Todos", "/Todos({Id})", "/Todos({Id})/Logo" }, + Assert.Equal(6, paths.Count()); + Assert.Equal(new[] { "/me", "/me/photo", "/me/photo/$value", "/Todos", "/Todos({Id})", "/Todos({Id})/Logo"}, paths.Select(p => p.GetPathItemName())); } } @@ -282,9 +282,17 @@ private static IEdmModel GetEdmModel(bool hasStream, string streamPropName) - - - + + + + + + + + + + + diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs index 1e9f2522..9d6bff92 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs @@ -30,7 +30,9 @@ public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOper ODataContext context = new ODataContext(model, settings); IEdmEntitySet todos = model.EntityContainer.FindEntitySet("Todos"); + IEdmSingleton me = model.EntityContainer.FindSingleton("me"); Assert.NotNull(todos); + Assert.NotNull(me); IEdmEntityType todo = model.SchemaElements.OfType().First(c => c.Name == "Todo"); IEdmStructuralProperty sp = todo.DeclaredStructuralProperties().First(c => c.Name == "Logo"); @@ -38,27 +40,45 @@ public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOper new ODataKeySegment(todos.EntityType()), new ODataStreamPropertySegment(sp.Name)); + IEdmEntityType user = model.SchemaElements.OfType().First(c => c.Name == "user"); + IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); + ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(me), + new ODataNavigationPropertySegment(navProperty), + new ODataStreamContentSegment()); + // Act var getOperation = _operationalHandler.CreateOperation(context, path); + var getOperation2 = _operationalHandler.CreateOperation(context, path2); // Assert Assert.NotNull(getOperation); + Assert.NotNull(getOperation2); Assert.Equal("Get media content for Todo from Todos", getOperation.Summary); + Assert.Equal("Get media content for the navigation property photo from me", getOperation2.Summary); Assert.NotNull(getOperation.Tags); + Assert.NotNull(getOperation2.Tags); + var tag = Assert.Single(getOperation.Tags); + var tag2 = Assert.Single(getOperation2.Tags); Assert.Equal("Todos.Todo", tag.Name); + Assert.Equal("me.profilePhoto", tag2.Name); Assert.NotNull(getOperation.Responses); + Assert.NotNull(getOperation2.Responses); Assert.Equal(2, getOperation.Responses.Count); + Assert.Equal(2, getOperation2.Responses.Count); Assert.Equal(new[] { "200", "default" }, getOperation.Responses.Select(r => r.Key)); + Assert.Equal(new[] { "200", "default" }, getOperation2.Responses.Select(r => r.Key)); if (enableOperationId) { Assert.Equal("Todos.Todo.GetLogo", getOperation.OperationId); + Assert.Equal("me.photo.GetContent", getOperation2.OperationId); } else { Assert.Null(getOperation.OperationId); + Assert.Null(getOperation2.OperationId); } } @@ -74,9 +94,17 @@ public static IEdmModel GetEdmModel() - - - + + + + + + + + + + + diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs index 14fe92d4..88533c86 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs @@ -28,6 +28,7 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation ODataContext context = new ODataContext(model, settings); IEdmEntitySet todos = model.EntityContainer.FindEntitySet("Todos"); + IEdmSingleton me = model.EntityContainer.FindSingleton("me"); Assert.NotNull(todos); IEdmEntityType todo = model.SchemaElements.OfType().First(c => c.Name == "Todo"); @@ -36,27 +37,45 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation new ODataKeySegment(todos.EntityType()), new ODataStreamPropertySegment(sp.Name)); + IEdmEntityType user = model.SchemaElements.OfType().First(c => c.Name == "user"); + IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); + ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(me), + new ODataNavigationPropertySegment(navProperty), + new ODataStreamContentSegment()); + // Act var getOperation = _operationalHandler.CreateOperation(context, path); + var getOperation2 = _operationalHandler.CreateOperation(context, path2); // Assert Assert.NotNull(getOperation); + Assert.NotNull(getOperation2); Assert.Equal("Update media content for Todo in Todos", getOperation.Summary); + Assert.Equal("Update media content for the navigation property photo in me", getOperation2.Summary); Assert.NotNull(getOperation.Tags); + Assert.NotNull(getOperation2.Tags); + var tag = Assert.Single(getOperation.Tags); + var tag2 = Assert.Single(getOperation2.Tags); Assert.Equal("Todos.Todo", tag.Name); + Assert.Equal("me.profilePhoto", tag2.Name); Assert.NotNull(getOperation.Responses); + Assert.NotNull(getOperation2.Responses); Assert.Equal(2, getOperation.Responses.Count); + Assert.Equal(2, getOperation2.Responses.Count); Assert.Equal(new[] { "204", "default" }, getOperation.Responses.Select(r => r.Key)); + Assert.Equal(new[] { "204", "default" }, getOperation2.Responses.Select(r => r.Key)); if (enableOperationId) { Assert.Equal("Todos.Todo.UpdateLogo", getOperation.OperationId); + Assert.Equal("me.photo.UpdateContent", getOperation2.OperationId); } else { Assert.Null(getOperation.OperationId); + Assert.Null(getOperation2.OperationId); } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs index 53f164f4..ee20c584 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/MediaEntityPathItemHandlerTests.cs @@ -59,8 +59,10 @@ public void CreateMediaEntityPathItemReturnsCorrectItem() // Arrange IEdmModel model = GetEdmModel(""); ODataContext context = new ODataContext(model); - var entitySet = model.EntityContainer.FindEntitySet("Todos"); + IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); + IEdmSingleton singleton = model.EntityContainer.FindSingleton("me"); Assert.NotNull(entitySet); // guard + Assert.NotNull(singleton); IEdmEntityType entityType = entitySet.EntityType(); IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); @@ -68,14 +70,30 @@ public void CreateMediaEntityPathItemReturnsCorrectItem() new ODataKeySegment(entityType), new ODataStreamPropertySegment(sp.Name)); + IEdmEntityType user = model.SchemaElements.OfType().First(c => c.Name == "user"); + IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); + ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(singleton), + new ODataNavigationPropertySegment(navProperty), + new ODataStreamContentSegment()); + // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); + var pathItem2 = _pathItemHandler.CreatePathItem(context, path2); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem2); Assert.NotNull(pathItem.Operations); + Assert.NotNull(pathItem2.Operations); Assert.NotEmpty(pathItem.Operations); + Assert.NotEmpty(pathItem2.Operations); Assert.Equal(2, pathItem.Operations.Count); + Assert.Equal(2, pathItem2.Operations.Count); Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Put }, pathItem.Operations.Select(o => o.Key)); + Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Put }, + pathItem2.Operations.Select(o => o.Key)); } [Theory] @@ -127,9 +145,10 @@ private void VerifyPathItemOperationsForStreamPropertySegment(string annotation, Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); + IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), - new ODataStreamContentSegment()); + new ODataStreamPropertySegment(sp.Name)); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); @@ -148,23 +167,35 @@ private void VerifyPathItemOperationsForStreamContentSegment(string annotation, IEdmModel model = GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); + IEdmSingleton singleton = model.EntityContainer.FindSingleton("me"); Assert.NotNull(entitySet); // guard + Assert.NotNull(singleton); IEdmEntityType entityType = entitySet.EntityType(); - IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); + IEdmEntityType user = model.SchemaElements.OfType().First(c => c.Name == "user"); + IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); + ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(singleton), + new ODataNavigationPropertySegment(navProperty), + new ODataStreamContentSegment()); + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), - new ODataStreamPropertySegment(sp.Name)); + new ODataStreamContentSegment()); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); + var pathItem2 = _pathItemHandler.CreatePathItem(context, path2); // Assert Assert.NotNull(pathItem); + Assert.NotNull(pathItem2); Assert.NotNull(pathItem.Operations); + Assert.NotNull(pathItem2.Operations); Assert.NotEmpty(pathItem.Operations); + Assert.NotEmpty(pathItem2.Operations); Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); + Assert.Equal(expected, pathItem2.Operations.Select(e => e.Key)); } private IEdmModel GetEdmModel(string annotation) @@ -180,11 +211,22 @@ private IEdmModel GetEdmModel(string annotation) - - + + + + + + + + + + - - {0} + + {0} + + + {0} From b19848dbaaad99089595835fd1f5df43332709d7 Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Tue, 15 Sep 2020 21:14:06 +0300 Subject: [PATCH 09/12] Adds support for creating a media entity (#8) * Generate stream paths for navigation properties * Refactor out stream path generation into separate function * Create base class for media entity operations handler * Add new stream segments conditional checks when creating a NavPropPath * Add Get and Put operation ids for single-valued nav. prop. paths * Update handler with support for both Entityset/Singleton stream paths * Update tests to validate the stream paths updates * Revert removed modifier * Add support for creating a media entity * Update tests to validate POST operation for creating media entity * Comment update * Refactor out common code into private methods * Remove unnecessary schema definition * Add application/json content type for RequestBody in media entity POST * Add application/json content in RequestBody * Nitpick: format code * Add application/json content type for media entities RequestBody/Response elements Co-authored-by: Irvine Sunday --- .../EntitySetPostOperationHandler.cs | 117 +++++++++--------- .../EntitySetGetOperationHandlerTests.cs | 8 +- .../EntitySetPostOperationHandlerTests.cs | 30 ++++- 3 files changed, 90 insertions(+), 65 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs index 5233ff25..9c87c52f 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs @@ -43,40 +43,13 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = EntitySet.EntityType().FullName() - } - }; - } - // The requestBody field contains a Request Body Object for the request body // that references the schema of the entity set’s entity type in the global schemas. operation.RequestBody = new OpenApiRequestBody { Required = true, Description = "New entity", - Content = new Dictionary - { - { - Constants.ApplicationJsonMediaType, new OpenApiMediaType - { - Schema = schema - } - } - } + Content = GetContentDescription() }; base.SetRequestBody(operation); @@ -85,25 +58,6 @@ protected override void SetRequestBody(OpenApiOperation operation) /// protected override void SetResponses(OpenApiOperation operation) { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForResponses) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = EntitySet.EntityType().FullName() - } - }; - } - operation.Responses = new OpenApiResponses { { @@ -111,16 +65,7 @@ protected override void SetResponses(OpenApiOperation operation) new OpenApiResponse { Description = "Created entity", - Content = new Dictionary - { - { - Constants.ApplicationJsonMediaType, - new OpenApiMediaType - { - Schema = schema - } - } - } + Content = GetContentDescription() } } }; @@ -159,5 +104,63 @@ protected override void AppendCustomParameters(OpenApiOperation operation) AppendCustomParameters(operation, insert.CustomHeaders, ParameterLocation.Header); } } + + /// + /// Get the entity content description. + /// + /// The entity content description. + private IDictionary GetContentDescription() + { + OpenApiSchema schema = GetEntitySchema(); + var content = new Dictionary(); + + if (EntitySet.EntityType().HasStream) + { + // TODO: Read the AcceptableMediaType annotation from model + content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + } + }); + } + + content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType + { + Schema = schema + }); + + return content; + } + + /// + /// Get the entity schema. + /// + /// The entity schema. + private OpenApiSchema GetEntitySchema() + { + OpenApiSchema schema = null; + + if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) + { + schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); + } + + if (schema == null) + { + schema = new OpenApiSchema + { + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = EntitySet.EntityType().FullName() + } + }; + } + + return schema; + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs index 6529d9f3..e921b39e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs @@ -326,12 +326,12 @@ public void CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool e } } - public static IEdmModel GetEdmModel(string annotation) + public static IEdmModel GetEdmModel(string annotation, bool hasStream = false) { const string template = @" - + @@ -341,12 +341,12 @@ public static IEdmModel GetEdmModel(string annotation) - {0} + {1} "; - string modelText = string.Format(template, annotation); + string modelText = string.Format(template, hasStream, annotation); IEdmModel model; IEnumerable errors; diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs index ad15568d..8f5fb295 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs @@ -6,6 +6,7 @@ using Microsoft.OData.Edm; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Tests; using Xunit; @@ -17,12 +18,14 @@ public class EntitySetPostOperationHandlerTests private EntitySetPostOperationHandler _operationHandler = new EntitySetPostOperationHandler(); [Theory] - [InlineData(true)] - [InlineData(false)] - public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOperationId) + [InlineData(true, true)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(false, false)] + public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOperationId, bool hasStream) { // Arrange - IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel(""); + IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel("", hasStream); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { @@ -47,6 +50,25 @@ public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOpera Assert.NotNull(post.Responses); Assert.Equal(2, post.Responses.Count); + if (hasStream) + { + // TODO: Read the AcceptableMediaType annotation from model + Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + Assert.NotNull(post.RequestBody); + // TODO: Read the AcceptableMediaType annotation from model + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + } + else + { + Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + Assert.NotNull(post.RequestBody); + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + } + if (enableOperationId) { Assert.Equal("Customers.Customer.CreateCustomer", post.OperationId); From 5598f06b2a75877fc8295535ced20690616ef929 Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Tue, 22 Sep 2020 15:27:52 +0300 Subject: [PATCH 10/12] Supports describing AcceptableMediaTypes from annotations (#9) * Generate stream paths for navigation properties * Refactor out stream path generation into separate function * Create base class for media entity operations handler * Add new stream segments conditional checks when creating a NavPropPath * Add Get and Put operation ids for single-valued nav. prop. paths * Update handler with support for both Entityset/Singleton stream paths * Update tests to validate the stream paths updates * Revert removed modifier * Add support for creating a media entity * Update tests to validate POST operation for creating media entity * Comment update * Refactor out common code into private methods * Remove unnecessary schema definition * Add application/json content type for RequestBody in media entity POST * Add application/json content in RequestBody * Nitpick: format code * Null condition check * Add application/json content type for media entities RequestBody/Response elements * Retrieve AcceptableMediaTypes for media entities from annotations * Add AcceptableMediaTypes OData term constant * Simplify code * Update tests to validate fetching of AcceptableMediaTypes from annotations * Get media stream structural property and nav, property annotations * Get media type for EntityType instead of EntitySet * Revert to original code Functionality refactored out to a separate method * Create local method for generating custom Edm model * Correct annotations target reference * Fix original code Co-authored-by: Irvine Sunday --- .../Edm/EdmAnnotationExtensions.cs | 2 +- .../EntitySetPostOperationHandler.cs | 25 ++++-- .../MediaEntityGetOperationHandler.cs | 16 +--- .../MediaEntityOperationalHandler.cs | 84 ++++++++++++++++-- .../MediaEntityPutOperationHandler.cs | 40 +-------- .../Capabilities/CapabilitiesConstants.cs | 5 ++ .../EntitySetGetOperationHandlerTests.cs | 13 ++- .../EntitySetPostOperationHandlerTests.cs | 88 ++++++++++++++++--- .../MediaEntityGetOperationHandlerTests.cs | 47 +++++++++- .../MediaEntityPutOperationHandlerTests.cs | 80 ++++++++++++----- 10 files changed, 291 insertions(+), 109 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs index f346e7b0..b5eb1e32 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs @@ -196,7 +196,7 @@ public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabu } } - return value.ToList(); + return value?.ToList(); }); } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs index 9c87c52f..381fd56b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs @@ -116,15 +116,28 @@ private IDictionary GetContentDescription() if (EntitySet.EntityType().HasStream) { - // TODO: Read the AcceptableMediaType annotation from model - content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + IEnumerable mediaTypes = Context.Model.GetCollection(EntitySet.EntityType(), + CapabilitiesConstants.AcceptableMediaTypes); + + if (mediaTypes != null) { - Schema = new OpenApiSchema + foreach (string item in mediaTypes) { - Type = "string", - Format = "binary" + content.Add(item, null); } - }); + } + else + { + // Default content type + content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + } + }); + } } content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs index d0c8fa41..da4b7077 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs @@ -9,7 +9,6 @@ using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Generator; using Microsoft.OpenApi.OData.Vocabulary.Capabilities; -using System.Collections.Generic; using System.Linq; namespace Microsoft.OpenApi.OData.Operation @@ -65,20 +64,7 @@ protected override void SetResponses(OpenApiOperation operation) new OpenApiResponse { Description = "Retrieved media content", - Content = new Dictionary - { - { - Constants.ApplicationOctetStreamMediaType, - new OpenApiMediaType - { - Schema = new OpenApiSchema - { - Type = "string", - Format = "binary" - } - } - } - } + Content = GetContentDescription() } } }; diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs index e1c7afdd..9629bae0 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs @@ -4,10 +4,12 @@ // ------------------------------------------------------------ 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.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using System.Collections.Generic; using System.Linq; @@ -83,18 +85,18 @@ protected override void SetExtensions(OpenApiOperation operation) /// protected string GetOperationId(string prefix, string identifier) { - Utils.CheckArgumentNull(prefix, nameof(prefix)); - Utils.CheckArgumentNull(identifier, nameof(identifier)); + Utils.CheckArgumentNullOrEmpty(prefix, nameof(prefix)); + Utils.CheckArgumentNullOrEmpty(identifier, nameof(identifier)); IList items = new List { NavigationSource.Name }; - var lastpath = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment); - foreach (var segment in Path.Segments.Skip(1)) + ODataSegment lastSegment = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment); + foreach (ODataSegment segment in Path.Segments.Skip(1)) { - if (segment == lastpath) + if (segment == lastSegment) { items.Add(prefix + Utils.UpperFirstChar(identifier)); break; @@ -110,5 +112,77 @@ protected string GetOperationId(string prefix, string identifier) return string.Join(".", items); } + + /// + /// Gets a media entity content description. + /// + /// The entity content description. + protected IDictionary GetContentDescription() + { + var content = new Dictionary(); + + OpenApiSchema schema = new OpenApiSchema + { + Type = "string", + Format = "binary" + }; + + IEdmVocabularyAnnotatable annotatableElement = null; + IEdmEntityType entityType = EntitySet != null ? EntitySet.EntityType() : Singleton.EntityType(); + ODataSegment lastSegmentStreamProp = Path.Segments.LastOrDefault(c => c is ODataStreamPropertySegment); + + if (lastSegmentStreamProp != null) + { + // Get the annotatable stream property + // The stream property can either be a structural type or navigation type property + IEdmProperty property = GetStructuralProperty(entityType, lastSegmentStreamProp.Identifier); + if (property == null) + { + property = GetNavigationProperty(entityType, lastSegmentStreamProp.Identifier); + } + + annotatableElement = property; + } + else + { + annotatableElement = entityType; + } + + // Fetch the respective AcceptableMediaTypes + IEnumerable mediaTypes = null; + if (annotatableElement != null) + { + mediaTypes = Context.Model.GetCollection(annotatableElement, + CapabilitiesConstants.AcceptableMediaTypes); + } + + if (mediaTypes != null) + { + foreach (string item in mediaTypes) + { + content.Add(item, null); + } + } + else + { + // Default content type + content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType + { + Schema = schema + }); + }; + + return content; + } + + private IEdmStructuralProperty GetStructuralProperty(IEdmEntityType entityType, string identifier) + { + return entityType.DeclaredStructuralProperties().FirstOrDefault(x => x.Name.Equals(identifier)); + } + + private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType, string identifier) + { + return entityType.DeclaredNavigationProperties().FirstOrDefault(x => x.Name.Equals(identifier)); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs index a6a33a68..eb5204c6 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.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 System.Linq; using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; @@ -58,48 +57,11 @@ protected override void SetBasicInfo(OpenApiOperation operation) /// protected override void SetRequestBody(OpenApiOperation operation) { - OpenApiSchema schema = null; - - if (Context.Settings.EnableDerivedTypesReferencesForRequestBody) - { - schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model); - } - - if (schema == null) - { - schema = new OpenApiSchema - { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = EntitySet != null ? EntitySet.EntityType().FullName() : Singleton.EntityType().FullName() - } - }; - } - operation.RequestBody = new OpenApiRequestBody { Required = true, Description = "New media content.", - Content = new Dictionary - { - { - Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType - { - Schema = new OpenApiSchema - { - Type = "string", - Format = "binary" - } - } - }, - { - Constants.ApplicationJsonMediaType, new OpenApiMediaType - { - Schema = schema - } - } - } + Content = GetContentDescription() }; base.SetRequestBody(operation); diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs index 11d5d493..2cd980f7 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs @@ -94,5 +94,10 @@ internal class CapabilitiesConstants /// Org.OData.Capabilities.V1.KeyAsSegmentSupported /// public const string KeyAsSegmentSupported = "Org.OData.Capabilities.V1.KeyAsSegmentSupported"; + + /// + /// Org.OData.Core.V1.AcceptableMediaTypes + /// + public const string AcceptableMediaTypes = "Org.OData.Core.V1.AcceptableMediaTypes"; } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs index e921b39e..32aa2f6f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetGetOperationHandlerTests.cs @@ -326,12 +326,12 @@ public void CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool e } } - public static IEdmModel GetEdmModel(string annotation, bool hasStream = false) + public static IEdmModel GetEdmModel(string annotation) { const string template = @" - + @@ -341,17 +341,14 @@ public static IEdmModel GetEdmModel(string annotation, bool hasStream = false) - {1} + {0} "; - string modelText = string.Format(template, hasStream, annotation); - IEdmModel model; - IEnumerable errors; - - bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out errors); + string modelText = string.Format(template, annotation); + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); Assert.True(result); return model; } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs index 8f5fb295..3417518e 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EntitySetPostOperationHandlerTests.cs @@ -4,11 +4,14 @@ // ------------------------------------------------------------ using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Tests; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using System.Xml.Linq; using Xunit; namespace Microsoft.OpenApi.OData.Operation.Tests @@ -25,7 +28,23 @@ public class EntitySetPostOperationHandlerTests public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOperationId, bool hasStream) { // Arrange - IEdmModel model = EntitySetGetOperationHandlerTests.GetEdmModel("", hasStream); + string qualifiedName = CapabilitiesConstants.AcceptableMediaTypes; + string annotation = $@" + + + application/todo + + "; + + // Assert + VerifyEntitySetPostOperation("", enableOperationId, hasStream); + VerifyEntitySetPostOperation(annotation, enableOperationId, hasStream); + } + + private void VerifyEntitySetPostOperation(string annotation, bool enableOperationId, bool hasStream) + { + // Arrange + IEdmModel model = GetEdmModel(annotation, hasStream); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); OpenApiConvertSettings settings = new OpenApiConvertSettings { @@ -52,21 +71,43 @@ public void CreateEntitySetPostOperationReturnsCorrectOperation(bool enableOpera if (hasStream) { - // TODO: Read the AcceptableMediaType annotation from model - Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); - Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationJsonMediaType)); - Assert.NotNull(post.RequestBody); - // TODO: Read the AcceptableMediaType annotation from model - Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); - Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + if (!string.IsNullOrEmpty(annotation)) + { + // RequestBody + Assert.Equal(2, post.RequestBody.Content.Keys.Count); + Assert.True(post.RequestBody.Content.ContainsKey("application/todo")); + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + // Response + Assert.Equal(2, post.Responses[Constants.StatusCode201].Content.Keys.Count); + Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey("application/todo")); + Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + } + else + { + // RequestBody + Assert.Equal(2, post.RequestBody.Content.Keys.Count); + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + // Response + Assert.Equal(2, post.Responses[Constants.StatusCode201].Content.Keys.Count); + Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationJsonMediaType)); + } } else { - Assert.True(post.Responses["201"].Content.ContainsKey(Constants.ApplicationJsonMediaType)); - + // RequestBody Assert.NotNull(post.RequestBody); + Assert.Equal(1, post.RequestBody.Content.Keys.Count); Assert.True(post.RequestBody.Content.ContainsKey(Constants.ApplicationJsonMediaType)); + + // Response + Assert.Equal(1, post.Responses[Constants.StatusCode201].Content.Keys.Count); + Assert.True(post.Responses[Constants.StatusCode201].Content.ContainsKey(Constants.ApplicationJsonMediaType)); } if (enableOperationId) @@ -186,5 +227,32 @@ public void CreateEntitySetPostReturnsSecurityForInsertRestrictions(bool enableA Assert.Empty(post.Security); } } + + private static IEdmModel GetEdmModel(string annotation, bool hasStream = false) + { + const string template = @" + + + + + + + + + + + + + {1} + + + +"; + + string modelText = string.Format(template, hasStream, annotation); + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); + Assert.True(result); + return model; + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs index 9d6bff92..fa0eed2c 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs @@ -5,7 +5,9 @@ using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; +using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using System.Linq; using System.Xml.Linq; using Xunit; @@ -22,7 +24,24 @@ public class MediaEntityGetOperationHandlerTests public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOperationId) { // Arrange - IEdmModel model = GetEdmModel(); + string qualifiedName = CapabilitiesConstants.AcceptableMediaTypes; + string annotation = $@" + + + image/png + image/jpeg + + "; + + // Assert + VerifyMediaEntityGetOperation("", enableOperationId); + VerifyMediaEntityGetOperation(annotation, enableOperationId); + } + + private void VerifyMediaEntityGetOperation(string annotation, bool enableOperationId) + { + // Arrange + IEdmModel model = GetEdmModel(annotation); OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId @@ -70,6 +89,23 @@ public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOper Assert.Equal(new[] { "200", "default" }, getOperation.Responses.Select(r => r.Key)); Assert.Equal(new[] { "200", "default" }, getOperation2.Responses.Select(r => r.Key)); + if (!string.IsNullOrEmpty(annotation)) + { + Assert.Equal(2, getOperation.Responses[Constants.StatusCode200].Content.Keys.Count); + Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey("image/png")); + Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey("image/jpeg")); + + Assert.Equal(1, getOperation2.Responses[Constants.StatusCode200].Content.Keys.Count); + Assert.True(getOperation2.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + } + else + { + Assert.Equal(1, getOperation.Responses[Constants.StatusCode200].Content.Keys.Count); + Assert.Equal(1, getOperation2.Responses[Constants.StatusCode200].Content.Keys.Count); + Assert.True(getOperation.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(getOperation2.Responses[Constants.StatusCode200].Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + } + if (enableOperationId) { Assert.Equal("Todos.Todo.GetLogo", getOperation.OperationId); @@ -82,9 +118,9 @@ public void CreateMediaEntityGetOperationReturnsCorrectOperation(bool enableOper } } - public static IEdmModel GetEdmModel() + public static IEdmModel GetEdmModel(string annotation) { - const string modelText = @" + const string template = @" @@ -106,9 +142,14 @@ public static IEdmModel GetEdmModel() + + {0} + "; + string modelText = string.Format(template, annotation); + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _); Assert.True(result); return model; diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs index 88533c86..7b410f89 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs @@ -4,7 +4,9 @@ // ------------------------------------------------------------ using Microsoft.OData.Edm; +using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using System.Linq; using Xunit; @@ -17,10 +19,27 @@ public class MediaEntityPutOperationHandlerTests [Theory] [InlineData(true)] [InlineData(false)] - public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperationId) + public void CreateMediaEntityPutOperationReturnsCorrectOperation(bool enableOperationId) { // Arrange - IEdmModel model = MediaEntityGetOperationHandlerTests.GetEdmModel(); + string qualifiedName = CapabilitiesConstants.AcceptableMediaTypes; + string annotation = $@" + + + image/png + image/jpeg + + "; + + // Assert + VerifyMediaEntityPutOperation("", enableOperationId); + VerifyMediaEntityPutOperation(annotation, enableOperationId); + } + + private void VerifyMediaEntityPutOperation(string annotation, bool enableOperationId) + { + // Arrange + IEdmModel model = MediaEntityGetOperationHandlerTests.GetEdmModel(annotation); OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId @@ -44,38 +63,55 @@ public void CreateEntityPutOperationReturnsCorrectOperation(bool enableOperation new ODataStreamContentSegment()); // Act - var getOperation = _operationalHandler.CreateOperation(context, path); - var getOperation2 = _operationalHandler.CreateOperation(context, path2); + var putOperation = _operationalHandler.CreateOperation(context, path); + var putOperation2 = _operationalHandler.CreateOperation(context, path2); // Assert - Assert.NotNull(getOperation); - Assert.NotNull(getOperation2); - Assert.Equal("Update media content for Todo in Todos", getOperation.Summary); - Assert.Equal("Update media content for the navigation property photo in me", getOperation2.Summary); - Assert.NotNull(getOperation.Tags); - Assert.NotNull(getOperation2.Tags); + Assert.NotNull(putOperation); + Assert.NotNull(putOperation2); + Assert.Equal("Update media content for Todo in Todos", putOperation.Summary); + Assert.Equal("Update media content for the navigation property photo in me", putOperation2.Summary); + Assert.NotNull(putOperation.Tags); + Assert.NotNull(putOperation2.Tags); - var tag = Assert.Single(getOperation.Tags); - var tag2 = Assert.Single(getOperation2.Tags); + var tag = Assert.Single(putOperation.Tags); + var tag2 = Assert.Single(putOperation2.Tags); Assert.Equal("Todos.Todo", tag.Name); Assert.Equal("me.profilePhoto", tag2.Name); - Assert.NotNull(getOperation.Responses); - Assert.NotNull(getOperation2.Responses); - Assert.Equal(2, getOperation.Responses.Count); - Assert.Equal(2, getOperation2.Responses.Count); - Assert.Equal(new[] { "204", "default" }, getOperation.Responses.Select(r => r.Key)); - Assert.Equal(new[] { "204", "default" }, getOperation2.Responses.Select(r => r.Key)); + Assert.NotNull(putOperation.Responses); + Assert.NotNull(putOperation2.Responses); + Assert.Equal(2, putOperation.Responses.Count); + Assert.Equal(2, putOperation2.Responses.Count); + Assert.Equal(new[] { "204", "default" }, putOperation.Responses.Select(r => r.Key)); + Assert.Equal(new[] { "204", "default" }, putOperation2.Responses.Select(r => r.Key)); + + if (!string.IsNullOrEmpty(annotation)) + { + Assert.Equal(2, putOperation.RequestBody.Content.Keys.Count); + Assert.True(putOperation.RequestBody.Content.ContainsKey("image/png")); + Assert.True(putOperation.RequestBody.Content.ContainsKey("image/jpeg")); + + Assert.Equal(1, putOperation2.RequestBody.Content.Keys.Count); + Assert.True(putOperation2.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + } + else + { + Assert.Equal(1, putOperation.RequestBody.Content.Keys.Count); + Assert.Equal(1, putOperation2.RequestBody.Content.Keys.Count); + Assert.True(putOperation.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + Assert.True(putOperation2.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); + } if (enableOperationId) { - Assert.Equal("Todos.Todo.UpdateLogo", getOperation.OperationId); - Assert.Equal("me.photo.UpdateContent", getOperation2.OperationId); + Assert.Equal("Todos.Todo.UpdateLogo", putOperation.OperationId); + Assert.Equal("me.photo.UpdateContent", putOperation2.OperationId); } else { - Assert.Null(getOperation.OperationId); - Assert.Null(getOperation2.OperationId); + Assert.Null(putOperation.OperationId); + Assert.Null(putOperation2.OperationId); } } } From 3236a8f77d79e8f841e29349b71dec2f33491cd0 Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Thu, 8 Oct 2020 14:48:21 +0300 Subject: [PATCH 11/12] Fix: Updates media entities Operation Ids (#10) * Update media entity operation id generation * Update tests * Refactor out operation id generation into abstract class * Update media entity tests Co-authored-by: Irvine Sunday --- .../MediaEntityGetOperationHandler.cs | 19 +++------- .../MediaEntityOperationalHandler.cs | 37 ++++++++++++++++--- .../MediaEntityPutOperationHandler.cs | 19 +++------- .../MediaEntityGetOperationHandlerTests.cs | 2 +- .../MediaEntityPutOperationHandlerTests.cs | 2 +- 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs index da4b7077..083d78a3 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityGetOperationHandler.cs @@ -25,30 +25,21 @@ internal class MediaEntityGetOperationHandler : MediaEntityOperationalHandler protected override void SetBasicInfo(OpenApiOperation operation) { // Summary - if (EntitySet != null) + if (IsNavigationPropertyPath) { - string typeName = EntitySet.EntityType().Name; - operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}"; + operation.Summary = $"Get media content for the navigation property {NavigationProperty.Name} from {NavigationSource.Name}"; } else { - operation.Summary = $"Get media content for the navigation property {NavigationProperty.Name} from {NavigationSource.Name}"; + string typeName = EntitySet.EntityType().Name; + operation.Summary = $"Get media content for {typeName} from {EntitySet.Name}"; } // OperationId if (Context.Settings.EnableOperationId) { string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; - - if (EntitySet != null) - { - string typeName = EntitySet.EntityType().Name; - operation.OperationId = $"{EntitySet.Name}.{typeName}.Get{Utils.UpperFirstChar(identifier)}"; - } - else // Singleton - { - operation.OperationId = GetOperationId("Get", identifier); - } + operation.OperationId = GetOperationId("Get", identifier); } base.SetBasicInfo(operation); diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs index 9629bae0..d43ffcaf 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs @@ -30,18 +30,31 @@ internal abstract class MediaEntityOperationalHandler : NavigationPropertyOperat /// protected IEdmSingleton Singleton { get; private set; } + /// + /// Gets/Sets flag indicating whether path is navigation property path + /// + protected bool IsNavigationPropertyPath { get; private set; } + /// protected override void Initialize(ODataContext context, ODataPath path) { - // The first segment will either be an entity set navigation source or a singleton navigation source. + // The first segment will either be an EntitySet navigation source or a Singleton navigation source ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet; if (EntitySet == null) { - // Singleton + Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton; + } + + // Check whether path is a navigation property path + IsNavigationPropertyPath = Path.Segments.Contains( + Path.Segments.Where(segment => segment is ODataNavigationPropertySegment).FirstOrDefault()); + + if (IsNavigationPropertyPath) + { + // Initialize navigation property paths from base base.Initialize(context, path); - Singleton = NavigationSource as IEdmSingleton; } } @@ -78,7 +91,7 @@ protected override void SetExtensions(OpenApiOperation operation) } /// - /// Retrieves the operation Id for a navigation property stream path. + /// Retrieves the operation Id for a media entity stream path. /// /// The http method identifier name. /// The stream segment identifier name. @@ -90,7 +103,7 @@ protected string GetOperationId(string prefix, string identifier) IList items = new List { - NavigationSource.Name + EntitySet?.Name ?? Singleton.Name }; ODataSegment lastSegment = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment); @@ -98,7 +111,19 @@ protected string GetOperationId(string prefix, string identifier) { if (segment == lastSegment) { - items.Add(prefix + Utils.UpperFirstChar(identifier)); + if (!IsNavigationPropertyPath) + { + string typeName = EntitySet?.EntityType().Name ?? Singleton.EntityType().Name; + items.Add(typeName); + items.Add(prefix + Utils.UpperFirstChar(identifier)); + } + else + { + // Remove the last navigation property segment for navigation property paths, + // as this will be included within the prefixed name of the operation id + items.Remove(NavigationProperty.Name); + items.Add(prefix + Utils.UpperFirstChar(NavigationProperty.Name) + Utils.UpperFirstChar(identifier)); + } break; } else diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs index eb5204c6..8aff1d0a 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityPutOperationHandler.cs @@ -25,30 +25,21 @@ internal class MediaEntityPutOperationHandler : MediaEntityOperationalHandler protected override void SetBasicInfo(OpenApiOperation operation) { // Summary - if (EntitySet != null) + if (IsNavigationPropertyPath) { - string typeName = EntitySet.EntityType().Name; - operation.Summary = $"Update media content for {typeName} in {EntitySet.Name}"; + operation.Summary = $"Update media content for the navigation property {NavigationProperty.Name} in {NavigationSource.Name}"; } else { - operation.Summary = $"Update media content for the navigation property {NavigationProperty.Name} in {NavigationSource.Name}"; + string typeName = EntitySet.EntityType().Name; + operation.Summary = $"Update media content for {typeName} in {EntitySet.Name}"; } // OperationId if (Context.Settings.EnableOperationId) { string identifier = Path.LastSegment.Kind == ODataSegmentKind.StreamContent ? "Content" : Path.LastSegment.Identifier; - - if (EntitySet != null) - { - string typeName = EntitySet.EntityType().Name; - operation.OperationId = $"{EntitySet.Name}.{typeName}.Update{Utils.UpperFirstChar(identifier)}"; - } - else - { - operation.OperationId = GetOperationId("Update", identifier); - } + operation.OperationId = GetOperationId("Update", identifier); } base.SetBasicInfo(operation); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs index fa0eed2c..c26574a5 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityGetOperationHandlerTests.cs @@ -109,7 +109,7 @@ private void VerifyMediaEntityGetOperation(string annotation, bool enableOperati if (enableOperationId) { Assert.Equal("Todos.Todo.GetLogo", getOperation.OperationId); - Assert.Equal("me.photo.GetContent", getOperation2.OperationId); + Assert.Equal("me.GetPhotoContent", getOperation2.OperationId); } else { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs index 7b410f89..7ec79556 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/MediaEntityPutOperationHandlerTests.cs @@ -106,7 +106,7 @@ private void VerifyMediaEntityPutOperation(string annotation, bool enableOperati if (enableOperationId) { Assert.Equal("Todos.Todo.UpdateLogo", putOperation.OperationId); - Assert.Equal("me.photo.UpdateContent", putOperation2.OperationId); + Assert.Equal("me.UpdatePhotoContent", putOperation2.OperationId); } else { From 63990d2762c83aee0ee50b346e0cd1a9201c1475 Mon Sep 17 00:00:00 2001 From: Irvine Sunday <40403681+irvinesunday@users.noreply.github.com> Date: Thu, 15 Oct 2020 09:22:51 +0300 Subject: [PATCH 12/12] Fix media entity nav. prop. path evaluation (#11) Fixes the condition evaluating whether a path has navigation property segments. Co-authored-by: Irvine Sunday --- .../Operation/MediaEntityOperationalHandler.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs index d43ffcaf..8fa28d09 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/MediaEntityOperationalHandler.cs @@ -61,12 +61,11 @@ protected override void Initialize(ODataContext context, ODataPath path) /// protected override void SetTags(OpenApiOperation operation) { - if (EntitySet == null) + if (IsNavigationPropertyPath) { - // Singleton base.SetTags(operation); } - else // Entityset + else { string tagIdentifier = EntitySet.Name + "." + EntitySet.EntityType().Name;