From d28ed09238c8c656b7103c96ecba25ac54106899 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Thu, 27 Jun 2019 17:06:53 -0700 Subject: [PATCH] Switch to use the latest Capabilities vocabulary, enable permission --- docs/csdl/capabilities.xml | 454 + docs/csdl/graph1.0_updated.xml | 16267 ++++++++++++++++ docs/csdl/graph1.0_withSecurity.xml | 445 + .../Annotations/Example.cs | 76 - .../Annotations/HttpRequest.cs | 84 - .../Annotations/HttpRequestProvider.cs | 120 - .../Annotations/HttpResponse.cs | 57 - .../Annotations/InlineExample.cs | 33 - .../Authorizations/AuthorizationProvider.cs | 102 - .../Capabilities/CapabilitiesConstants.cs | 93 - .../Capabilities/CapabilitiesExtensions.cs | 327 - .../Capabilities/CapabilitiesRestrictions.cs | 57 - .../Capabilities/CapabilitiesTermKind.cs | 163 - .../Capabilities/CustomHeaders.cs | 31 - .../Capabilities/CustomParameter.cs | 40 - .../Capabilities/CustomQueryOptions.cs | 31 - .../Capabilities/ICapabilitiesRestrictions.cs | 29 - .../ModificationQueryOptionsType.cs | 43 - .../Capabilities/ReadRestrictions.cs | 96 - .../RecordExpressionExtensions.cs | 144 - .../Capabilities/SupportedRestrictions.cs | 46 - .../Common/Utils.cs | 18 + .../Core/ComplexExampleValue.cs | 18 - .../Core/EntityExampleValue.cs | 18 - .../Core/ExternalExampleValue.cs | 18 - .../Edm/EdmAnnotationExtensions.cs | 473 +- .../Edm/ODataContext.cs | 34 +- .../Edm/ODataTypeCastSegment.cs | 2 +- .../Edm/RecordExpressionExtensions.cs | 104 +- .../Generator/OpenApiParameterGenerator.cs | 23 +- .../OpenApiSecurityRequirementGenerator.cs | 36 +- .../OpenApiSecuritySchemeGenerator.cs | 9 +- .../OData/IEdmExpressionExtensions.cs | 137 + .../ODataCollectValue.cs} | 13 +- .../ODataComplexValue.cs} | 10 +- .../ODataEntityValue.cs} | 10 +- .../ODataPrimitiveValue.cs} | 18 +- .../ODataResourceValue.cs} | 12 +- .../ExampleValue.cs => OData/ODataValue.cs} | 12 +- .../EdmOperationImportOperationHandler.cs | 2 - .../Operation/EdmOperationOperationHandler.cs | 43 +- .../Operation/EntityDeleteOperationHandler.cs | 35 + .../Operation/EntityGetOperationHandler.cs | 52 + .../Operation/EntityPatchOperationHandler.cs | 35 + .../Operation/EntitySetGetOperationHandler.cs | 35 + .../Operation/EntitySetOperationHandler.cs | 2 - .../EntitySetPostOperationHandler.cs | 35 + .../Operation/OperationHandler.cs | 113 +- .../Operation/OperationHandlerProvider.cs | 2 +- .../Operation/SingletonGetOperationHandler.cs | 37 + .../Operation/SingletonOperationHandler.cs | 2 - .../SingletonPatchOperationHandler.cs | 37 + .../PathItem/EntityPathItemHandler.cs | 13 +- .../PathItem/EntitySetPathItemHandler.cs | 8 +- .../NavigationPropertyPathItemHandler.cs | 18 +- .../OperationImportPathItemHandler.cs | 9 +- .../PathItem/PathItemHandler.cs | 2 +- .../PathItem/PathItemHandlerProvider.cs | 2 +- .../PathItem/SingletonPathItemHandler.cs | 8 +- .../Properties/SRResource.Designer.cs | 11 +- .../Properties/SRResource.resx | 3 + .../Authorization}/ApiKey.cs | 8 +- .../Authorization}/Authorization.cs | 13 +- .../Authorization}/AuthorizationConstants.cs | 2 +- .../Authorization}/AuthorizationScope.cs | 8 +- .../Authorization}/Http.cs | 8 +- .../Authorization}/OAuth2AuthCode.cs | 8 +- .../Authorization}/OAuth2ClientCredentials.cs | 8 +- .../Authorization}/OAuth2Implicit.cs | 8 +- .../Authorization}/OAuth2Password.cs | 8 +- .../Authorization}/OAuthAuthorization.cs | 10 +- .../Authorization}/OpenIDConnect.cs | 8 +- .../Authorization}/SecurityScheme.cs | 9 +- .../Capabilities/CapabilitiesConstants.cs | 98 + .../CollectionPropertyRestrictionsType.cs} | 66 +- .../Capabilities/CountRestrictionsType.cs} | 32 +- .../Capabilities}/CustomParameter.cs | 38 +- .../Capabilities/DeepInsertSupportType.cs} | 31 +- .../Capabilities/DeepUpdateSupportType.cs} | 31 +- .../Capabilities/DeleteRestrictionsType.cs} | 52 +- .../Capabilities/ExpandRestrictionsType.cs} | 29 +- .../FilterExpressionRestrictionType.cs | 44 + .../Capabilities/FilterRestrictionsType.cs} | 47 +- .../Capabilities/InsertRestrictionsType.cs} | 47 +- .../ModificationQueryOptionsType.cs | 75 + .../NavigationRestrictionsType.cs} | 146 +- .../Capabilities/OperationRestrictionType.cs} | 37 +- .../Capabilities/PermissionType.cs | 34 +- .../Capabilities/ReadRestrictionsType.cs | 99 + .../Capabilities/ScopeType.cs | 35 +- .../Capabilities/SearchRestrictionsType.cs} | 34 +- .../Capabilities/SelectSupportType.cs | 45 +- .../Capabilities/SortRestrictionsType.cs} | 32 +- .../Capabilities/UpdateRestrictionsType.cs} | 47 +- .../Vocabulary/Core/ComplexExampleValue.cs | 14 + .../Vocabulary/Core/EntityExampleValue.cs | 14 + .../Vocabulary/Core/ExampleValue.cs | 34 + .../Core/ExternalExampleValue.cs} | 17 +- .../Vocabulary/Core/PrimitiveExampleValue.cs | 49 + .../Vocabulary/Core/ResourceExampleValue.cs | 38 + .../IRecord.cs} | 12 +- .../Vocabulary/TermAttribute.cs | 52 + .../VocabularyAnnotationsExtensions.cs | 89 + .../Annotations/HttpRequestProviderTests.cs | 308 - .../Annotations/HttpRequestTests.cs | 310 - .../AuthorizationProviderTests.cs | 130 - .../Capabilities/CountRestrictionsTests.cs | 149 - .../Capabilities/DeleteRestrictionsTests.cs | 136 - .../Capabilities/IndexableByKeyTests.cs | 110 - .../Capabilities/InsertRestrictionsTests.cs | 136 - .../Capabilities/SkipSupportedTests.cs | 112 - .../Capabilities/TopSupportedTests.cs | 113 - .../Capabilities/UpdateRestrictionsTests.cs | 138 - .../Common/EdmModelHelper.cs | 2 +- .../EdmVocabularyAnnotationExtensionsTests.cs | 253 + ...icrosoft.OpenAPI.OData.Reader.Tests.csproj | 7 +- .../EdmActionOperationHandlerTests.cs | 2 +- .../EdmFunctionOperationHandlerTests.cs | 2 +- .../SingletonGetOperationHandlerTests.cs | 2 +- .../SingletonPatchOperationHandlerTests.cs | 159 + .../PathItem/EntityPathItemHandlerTests.cs | 90 +- .../PathItem/EntitySetPathItemHandlerTests.cs | 87 +- .../OperationImportPathItemHandlerTests.cs | 93 +- .../PathItem/SingletonPathItemHandlerTests.cs | 92 +- .../Vocabulary/Authorization/ApiKeyTests.cs | 119 + .../Authorization/AuthorizationScopeTests.cs | 94 + .../Authorization/AuthorizationTests.cs | 79 + .../AuthorizationVocabularyTests.cs | 90 + .../Vocabulary/Authorization/HttpTests.cs | 111 + .../Authorization/OAuth2AuthCodeTests.cs | 110 + .../OAuth2ClientCredentialsTests.cs | 105 + .../Authorization/OAuth2ImplicitTests.cs | 105 + .../Authorization/OAuth2PasswordTests.cs | 110 + .../Authorization/OpenIDConnectTests.cs | 102 + .../Authorization/SecuritySchemeTests.cs | 133 + .../Capabilities/BatchSupportedTests.cs | 3 +- .../Capabilities/CapabilitiesModelHelper.cs | 3 +- ...CollectionPropertyRestrictionsTypeTests.cs | 78 + .../CountRestrictionsTypeTests.cs | 107 + .../Capabilities/CustomParameterTests.cs | 126 + .../DeepInsertSupportTypeTests.cs | 79 + .../DeepUpdateSupportTypeTests.cs | 79 + .../DeleteRestrictionsTypeTests.cs | 171 + .../ExpandRestrictionsTypeTests.cs} | 53 +- .../FilterRestrictionsTypeTests.cs} | 69 +- .../InsertRestrictionsTypeTests.cs | 193 + .../KeyAsSegmentSupportedTests.cs | 39 +- .../ModificationQueryOptionsTypeTests.cs | 114 + .../NavigationRestrictionsTypeTests.cs} | 174 +- .../OperationRestrictionTypeTests.cs | 123 + .../Capabilities/PermissionTypeTests.cs | 123 + .../Capabilities/ReadRestrictionsTypeTests.cs | 173 + .../Vocabulary/Capabilities/ScopeTypeTests.cs | 104 + .../SearchRestrictionsTypeTests.cs} | 73 +- .../Capabilities/SelectSupportTypeTests.cs | 113 + .../SortRestrictionsTypeTests.cs} | 34 +- .../UpdateRestrictionsTypeTests.cs | 252 + .../Core/PrimitiveExampleValueTests.cs | 138 + 158 files changed, 23442 insertions(+), 4291 deletions(-) create mode 100644 docs/csdl/capabilities.xml create mode 100644 docs/csdl/graph1.0_updated.xml delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequest.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequestProvider.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Annotations/HttpResponse.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Annotations/InlineExample.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationProvider.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesConstants.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesExtensions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesRestrictions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesTermKind.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomHeaders.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomParameter.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomQueryOptions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/ICapabilitiesRestrictions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/ModificationQueryOptionsType.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/ReadRestrictions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/RecordExpressionExtensions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Capabilities/SupportedRestrictions.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Core/ComplexExampleValue.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Core/EntityExampleValue.cs delete mode 100644 src/Microsoft.OpenApi.OData.Reader/Core/ExternalExampleValue.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/TopSupported.cs => OData/ODataCollectValue.cs} (52%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/SkipSupported.cs => OData/ODataComplexValue.cs} (52%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/BatchSupported.cs => OData/ODataEntityValue.cs} (51%) rename src/Microsoft.OpenApi.OData.Reader/{Core/PrimitiveExampleValue.cs => OData/ODataPrimitiveValue.cs} (50%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/KeyAsSegmentSupported.cs => OData/ODataResourceValue.cs} (56%) rename src/Microsoft.OpenApi.OData.Reader/{Core/ExampleValue.cs => OData/ODataValue.cs} (60%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/ApiKey.cs (88%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/Authorization.cs (90%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/AuthorizationConstants.cs (97%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/AuthorizationScope.cs (84%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/Http.cs (85%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OAuth2AuthCode.cs (84%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OAuth2ClientCredentials.cs (81%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OAuth2Implicit.cs (82%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OAuth2Password.cs (81%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OAuthAuthorization.cs (87%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/OpenIDConnect.cs (84%) rename src/Microsoft.OpenApi.OData.Reader/{Authorizations => Vocabulary/Authorization}/SecurityScheme.cs (81%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/CollectionPropertyRestrictions.cs => Vocabulary/Capabilities/CollectionPropertyRestrictionsType.cs} (53%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/CountRestrictions.cs => Vocabulary/Capabilities/CountRestrictionsType.cs} (78%) rename src/Microsoft.OpenApi.OData.Reader/{Annotations => Vocabulary/Capabilities}/CustomParameter.cs (58%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/DeepInsertSupported.cs => Vocabulary/Capabilities/DeepInsertSupportType.cs} (55%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/DeepUpdateSupported.cs => Vocabulary/Capabilities/DeepUpdateSupportType.cs} (55%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/DeleteRestrictions.cs => Vocabulary/Capabilities/DeleteRestrictionsType.cs} (68%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/ExpandRestrictions.cs => Vocabulary/Capabilities/ExpandRestrictionsType.cs} (71%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterExpressionRestrictionType.cs rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/FilterRestrictions.cs => Vocabulary/Capabilities/FilterRestrictionsType.cs} (65%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/InsertRestrictions.cs => Vocabulary/Capabilities/InsertRestrictionsType.cs} (71%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ModificationQueryOptionsType.cs rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/NavigationRestrictions.cs => Vocabulary/Capabilities/NavigationRestrictionsType.cs} (55%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/OperationRestrictions.cs => Vocabulary/Capabilities/OperationRestrictionType.cs} (50%) rename src/Microsoft.OpenApi.OData.Reader/{ => Vocabulary}/Capabilities/PermissionType.cs (58%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ReadRestrictionsType.cs rename src/Microsoft.OpenApi.OData.Reader/{ => Vocabulary}/Capabilities/ScopeType.cs (60%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/SearchRestrictions.cs => Vocabulary/Capabilities/SearchRestrictionsType.cs} (82%) rename src/Microsoft.OpenApi.OData.Reader/{ => Vocabulary}/Capabilities/SelectSupportType.cs (57%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/SortRestrictions.cs => Vocabulary/Capabilities/SortRestrictionsType.cs} (81%) rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/UpdateRestrictions.cs => Vocabulary/Capabilities/UpdateRestrictionsType.cs} (71%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ComplexExampleValue.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/EntityExampleValue.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExampleValue.cs rename src/Microsoft.OpenApi.OData.Reader/{Annotations/ExternalExample.cs => Vocabulary/Core/ExternalExampleValue.cs} (57%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/PrimitiveExampleValue.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ResourceExampleValue.cs rename src/Microsoft.OpenApi.OData.Reader/{Capabilities/IndexableByKey.cs => Vocabulary/IRecord.cs} (56%) create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/TermAttribute.cs create mode 100644 src/Microsoft.OpenApi.OData.Reader/Vocabulary/VocabularyAnnotationsExtensions.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestProviderTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Authorizations/AuthorizationProviderTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CountRestrictionsTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/DeleteRestrictionsTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/IndexableByKeyTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/InsertRestrictionsTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SkipSupportedTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/TopSupportedTests.cs delete mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/UpdateRestrictionsTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/EdmVocabularyAnnotationExtensionsTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/ApiKeyTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationScopeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationVocabularyTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/HttpTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2AuthCodeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ClientCredentialsTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ImplicitTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2PasswordTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OpenIDConnectTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/SecuritySchemeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{ => Vocabulary}/Capabilities/BatchSupportedTests.cs (98%) rename test/Microsoft.OpenAPI.OData.Reader.Tests/{ => Vocabulary}/Capabilities/CapabilitiesModelHelper.cs (97%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CollectionPropertyRestrictionsTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CountRestrictionsTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CustomParameterTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepInsertSupportTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepUpdateSupportTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeleteRestrictionsTypeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{Capabilities/ExpandRestrictionsTests.cs => Vocabulary/Capabilities/ExpandRestrictionsTypeTests.cs} (70%) rename test/Microsoft.OpenAPI.OData.Reader.Tests/{Capabilities/FilterRestrictionsTests.cs => Vocabulary/Capabilities/FilterRestrictionsTypeTests.cs} (62%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/InsertRestrictionsTypeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{ => Vocabulary}/Capabilities/KeyAsSegmentSupportedTests.cs (59%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ModificationQueryOptionsTypeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{Capabilities/NavigationRestrictionsTests.cs => Vocabulary/Capabilities/NavigationRestrictionsTypeTests.cs} (55%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/OperationRestrictionTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/PermissionTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ReadRestrictionsTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ScopeTypeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{Capabilities/SearchRestrictionsTests.cs => Vocabulary/Capabilities/SearchRestrictionsTypeTests.cs} (77%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SelectSupportTypeTests.cs rename test/Microsoft.OpenAPI.OData.Reader.Tests/{Capabilities/SortRestrictionsTests.cs => Vocabulary/Capabilities/SortRestrictionsTypeTests.cs} (82%) create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/UpdateRestrictionsTypeTests.cs create mode 100644 test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Core/PrimitiveExampleValueTests.cs diff --git a/docs/csdl/capabilities.xml b/docs/csdl/capabilities.xml new file mode 100644 index 0000000..526157d --- /dev/null +++ b/docs/csdl/capabilities.xml @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -mailboxSettings + + + + + + mailboxSettings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/csdl/graph1.0_updated.xml b/docs/csdl/graph1.0_updated.xml new file mode 100644 index 0000000..0d36e8b --- /dev/null +++ b/docs/csdl/graph1.0_updated.xml @@ -0,0 +1,16267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Capabilities.V1.NavigationType/Single + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Core.V1.Permission/Read + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Org.OData.Core.V1.Permission/Read + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/csdl/graph1.0_withSecurity.xml b/docs/csdl/graph1.0_withSecurity.xml index adeefbd..56248c1 100644 --- a/docs/csdl/graph1.0_withSecurity.xml +++ b/docs/csdl/graph1.0_withSecurity.xml @@ -2,6 +2,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + -mailboxSettings + + + + + + mailboxSettings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs b/src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs deleted file mode 100644 index 7b9468b..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/Example.cs +++ /dev/null @@ -1,76 +0,0 @@ -// ------------------------------------------------------------ -// 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.Vocabularies; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Annotations -{ - /// - /// Org.OData.Core.V1.Example - /// - internal abstract class Example - { - /// - /// Description. - /// - public string Description { get; set; } - - /// - /// Init the . - /// - /// The input record. - public virtual void Init(IEdmRecordExpression record) - { - Utils.CheckArgumentNull(record, nameof(record)); - - // Description - Description = record.GetString("Description"); - } - - /// - /// Creat the corresponding example object. - /// - /// The input record. - /// The created example object. - public static Example CreateExample(IEdmRecordExpression record) - { - if (record == null || record.DeclaredType == null) - { - return null; - } - - IEdmComplexType complexType = record.DeclaredType.Definition as IEdmComplexType; - if (complexType == null) - { - return null; - } - - Example example = null; - switch (complexType.FullTypeName()) - { - case "Org.OData.Core.V1.ExternalExample": - example = new ExternalExample(); - break; - - case "Org.OData.Core.V1.InlineExample": - example = new InlineExample(); - break; - - default: - break; - } - - if (example != null) - { - example.Init(record); - } - - return example; - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequest.cs b/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequest.cs deleted file mode 100644 index 5d9552d..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequest.cs +++ /dev/null @@ -1,84 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Authorizations; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Annotations -{ - /// - /// Org.OData.Core.V1.HttpRequest - /// - internal class HttpRequest - { - /// - /// The description. - /// - public string Description { get; set; } - - /// - /// The MethodDescription. - /// - public string MethodDescription { get; set; } - - /// - /// The MethodType. - /// - public string MethodType { get; set; } - - /// - /// The Custom Query Options. - /// - public IList CustomQueryOptions { get; set; } - - /// - /// The custom Headers. - /// - public IList CustomHeaders { get; set; } - - /// - /// The http responses. - /// - public IList HttpResponses { get; set; } - - /// - /// The security sechems. - /// - public IList SecuritySchemes { get; set; } - - /// - /// Init the . - /// - /// The input record. - public virtual void Init(IEdmRecordExpression record) - { - Utils.CheckArgumentNull(record, nameof(record)); - - // Description. - Description = record.GetString("Description"); - - // MethodDescription. - MethodDescription = record.GetString("MethodDescription"); - - // MethodType. - MethodType = record.GetString("MethodType"); - - // CustomQueryOptions - CustomQueryOptions = record.GetCollection("CustomQueryOptions", (s, r) => s.Init(r as IEdmRecordExpression)); - - // CustomHeaders - CustomHeaders = record.GetCollection("CustomHeaders", (s, r) => s.Init(r as IEdmRecordExpression)); - - // HttpResponses - HttpResponses = record.GetCollection("HttpResponses", (s, r) => s.Init(r as IEdmRecordExpression)); - - // SecuritySchemes - SecuritySchemes = record.GetCollection("SecuritySchemes", (s, r) => s.Init(r as IEdmRecordExpression)); - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequestProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequestProvider.cs deleted file mode 100644 index 1fee486..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpRequestProvider.cs +++ /dev/null @@ -1,120 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Annotations -{ - /// - /// Org.OData.Core.V1.HttpRequests provider - /// - internal class HttpRequestProvider - { - /// - /// Annotatable: EntitySet Singleton ActionImport FunctionImport Action Function - /// Collection(Core.HttpRequest) - /// - private IDictionary> _requests - = new Dictionary>(); - - /// - /// Gets the Edm model. - /// - public IEdmModel Model { get; } - - /// - /// Gets the Edm Term. - /// - public IEdmTerm Term { get; } - - /// - /// Initializes a new instance of class. - /// - /// The Edm model. - public HttpRequestProvider(IEdmModel model) - { - Utils.CheckArgumentNull(model, nameof(model)); - - Term = model.FindTerm("Org.OData.Core.V1.HttpRequests"); - - Model = model; - } - - /// - /// Gets Org.OData.Core.V1.HttpRequest. - /// - /// The target. - /// The request method. - /// The Org.OData.Core.V1.HttpRequest or null. - public HttpRequest GetHttpRequest(IEdmVocabularyAnnotatable target, string method) - { - Utils.CheckArgumentNull(target, nameof(target)); - Utils.CheckArgumentNull(method, nameof(method)); - - var requests = GetHttpRequests(target); - return requests?.FirstOrDefault(e => string.Equals(e.MethodType, method, System.StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Gets the collection of Org.OData.Core.V1.HttpRequest for a given . - /// - /// The target. - /// The collection of Org.OData.Core.V1.HttpRequest - public IEnumerable GetHttpRequests(IEdmVocabularyAnnotatable target) - { - Utils.CheckArgumentNull(target, nameof(target)); - - if (Term == null) - { - return null; - } - - // Search the cache. - if (_requests.TryGetValue(target, out IList value)) - { - return value; - } - - IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(target, Term); - if (annotation == null) - { - IEdmNavigationSource navigationSource = target as IEdmNavigationSource; - - // if not, search the entity type. - if (navigationSource != null) - { - IEdmEntityType entityType = navigationSource.EntityType(); - annotation = Model.GetVocabularyAnnotation(entityType, Term); - } - } - - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Collection) - { - _requests[target] = null; - return null; - } - - IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value; - var httpRequests = new List(); - foreach (var item in collection.Elements) - { - IEdmRecordExpression record = (IEdmRecordExpression)item; - HttpRequest newRequest = new HttpRequest(); - newRequest.Init(record); - httpRequests.Add(newRequest); - } - - _requests[target] = httpRequests; - return httpRequests; - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpResponse.cs b/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpResponse.cs deleted file mode 100644 index ccd5658..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/HttpResponse.cs +++ /dev/null @@ -1,57 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Annotations -{ - /// - /// The Org.OData.Core.v1.HttpResponse - /// - internal class HttpResponse - { - /// - /// Description. - /// - public string Description { get; set; } - - /// - /// ResponseCode - /// - public string ResponseCode { get; set; } - - /// - /// Examples - /// - public IEnumerable Examples { get; set; } - - /// - /// Int the . - /// - /// The input record. - public void Init(IEdmRecordExpression record) - { - // ResponseCode - ResponseCode = record.GetString("ResponseCode"); - - // Description - Description = record.GetString("Description"); - - // Examples - Examples = record.GetCollection("Examples", r => - { - IEdmRecordExpression itemRecord = r as IEdmRecordExpression; - if (itemRecord != null) - { - return Example.CreateExample(itemRecord); - } - - return null; - }); - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/InlineExample.cs b/src/Microsoft.OpenApi.OData.Reader/Annotations/InlineExample.cs deleted file mode 100644 index bb03ddd..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/InlineExample.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ------------------------------------------------------------ -// 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.Vocabularies; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Annotations -{ - /// - /// Complex type Org.OData.Core.V1.InlineExample - /// - internal class InlineExample : Example - { - /// - /// InlineValue - /// - public string InlineValue { get; set; } - - /// - /// Init the . - /// - /// The record. - public override void Init(IEdmRecordExpression record) - { - base.Init(record); - - // InlineValue - InlineValue = record.GetString("InlineValue"); - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationProvider.cs deleted file mode 100644 index 3a72321..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationProvider.cs +++ /dev/null @@ -1,102 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Authorizations -{ - /// - /// The default 'Org.OData.Core.V1.Authorization' provider. - /// - internal class AuthorizationProvider - { - /// - /// Annotatable: EntitySet Singleton ActionImport FunctionImport Action Function - /// Collection(Core.HttpRequest) - /// - private IDictionary> _authorizations - = new Dictionary>(); - - /// - /// Gets the Edm model. - /// - public IEdmModel Model { get; } - - /// - /// Gets the Edm Term. - /// - public IEdmTerm Term { get; } - - /// - /// Initializes a new instance of class. - /// - /// The Edm model. - public AuthorizationProvider(IEdmModel model) - { - Utils.CheckArgumentNull(model, nameof(model)); - - Term = model.FindTerm(AuthorizationConstants.Authorizations); - - Model = model; - } - - /// - /// Gets the collections for a given target in the given Edm model. - /// - /// The Edm target. - /// The collections. - public virtual IEnumerable GetAuthorizations(IEdmVocabularyAnnotatable target) - { - Utils.CheckArgumentNull(target, nameof(target)); - - if (_authorizations.TryGetValue(target, out IEnumerable value)) - { - return value; - } - - if (Term == null) - { - return Enumerable.Empty(); - } - - value = RetrieveAuthorizations(target); - _authorizations[target] = value; - return value; - } - - /// - /// Create the corresponding Authorization object. - /// - /// The input record. - /// The created object. - private IEnumerable RetrieveAuthorizations(IEdmVocabularyAnnotatable target) - { - IEdmVocabularyAnnotation annotation = Model.GetVocabularyAnnotation(target, Term); - if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection) - { - IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value; - foreach (var item in collection.Elements) - { - IEdmRecordExpression record = item as IEdmRecordExpression; - if (record == null || record.DeclaredType == null) - { - continue; - } - - Authorization auth = Authorization.CreateAuthorization(record); - if (auth != null) - { - yield return auth; - } - } - } - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesConstants.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesConstants.cs deleted file mode 100644 index 0a43e20..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesConstants.cs +++ /dev/null @@ -1,93 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Constant values for Capabilities Vocabulary - /// - internal class CapabilitiesConstants - { - /// - /// The namespace of Capabilities annotation. - /// - public const string Namespace = "Org.OData.Capabilities.V1"; - - /// - /// Org.OData.Capabilities.V1.ChangeTracking - /// - public const string ChangeTracking = Namespace + ".ChangeTracking"; - - /// - /// Org.OData.Capabilities.V1.FilterRestrictions - /// - public const string FilterRestrictions = Namespace + ".FilterRestrictions"; - - /// - /// Org.OData.Capabilities.V1.SortRestrictions - /// - public const string SortRestrictions = Namespace + ".SortRestrictions"; - - /// - /// Org.OData.Capabilities.V1.NavigationRestrictions - /// - public const string NavigationRestrictions = Namespace + ".NavigationRestrictions"; - - /// - /// Org.OData.Capabilities.V1.SearchRestrictions - /// - public const string SearchRestrictions = Namespace + ".SearchRestrictions"; - - /// - /// Org.OData.Capabilities.V1.CountRestrictions - /// - public const string CountRestrictions = Namespace + ".CountRestrictions"; - - /// - /// Org.OData.Capabilities.V1.ExpandRestrictions - /// - public const string ExpandRestrictions = Namespace + ".ExpandRestrictions"; - - /// - /// Org.OData.Capabilities.V1.DeleteRestrictions - /// - public const string DeleteRestrictions = Namespace + ".DeleteRestrictions"; - - /// - /// Org.OData.Capabilities.V1.DeleteRestrictions - /// - public const string UpdateRestrictions = Namespace + ".UpdateRestrictions"; - - /// - /// Org.OData.Capabilities.V1.InsertRestrictions - /// - public const string InsertRestrictions = Namespace + ".InsertRestrictions"; - - /// - /// Org.OData.Capabilities.V1.TopSupported - /// - public const string TopSupported = Namespace + ".TopSupported"; - - /// - /// Org.OData.Capabilities.V1.SkipSupported - /// - public const string SkipSupported = Namespace + ".SkipSupported"; - - /// - /// Org.OData.Capabilities.V1.BatchSupported - /// - public const string BatchSupported = Namespace + ".BatchSupported"; - - /// - /// Org.OData.Capabilities.V1.IndexableByKey - /// - public const string IndexableByKey = Namespace + ".IndexableByKey"; - - /// - /// Org.OData.Capabilities.V1.KeyAsSegmentSupported - /// - public const string KeyAsSegmentSupported = Namespace + ".KeyAsSegmentSupported"; - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesExtensions.cs deleted file mode 100644 index 91d2613..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesExtensions.cs +++ /dev/null @@ -1,327 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Properties; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// The class provides the functionality for the capabilities annotation. - /// - internal static class CapabilitiesExtensions - { - private static IDictionary> _capabilitesRestrictions; - private static IEdmModel _savedModel = null; - private static object _objectLock = new object(); - - /// - /// Gets Org.OData.Capabilities.V1.SearchRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.SearchRestrictions or null. - public static SearchRestrictions GetSearchRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.SearchRestrictions) as SearchRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.FilterRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.FilterRestrictions or null. - public static FilterRestrictions GetFilterRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.FilterRestrictions) as FilterRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.NavigationRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.NavigationRestrictions or null. - public static NavigationRestrictions GetNavigationRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.NavigationRestrictions) as NavigationRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.ExpandRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.ExpandRestrictions or null. - public static ExpandRestrictions GetExpandRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.ExpandRestrictions) as ExpandRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.DeleteRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.DeleteRestrictions or null. - public static DeleteRestrictions GetDeleteRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.DeleteRestrictions) as DeleteRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.UpdateRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.UpdateRestrictions or null. - public static UpdateRestrictions GetUpdateRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.UpdateRestrictions) as UpdateRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.InsertRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.InsertRestrictions or null. - public static InsertRestrictions GetInsertRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.InsertRestrictions) as InsertRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.SortRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.SortRestrictions or null. - public static SortRestrictions GetSortRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.SortRestrictions) as SortRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.CountRestrictions. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.CountRestrictions or null. - public static CountRestrictions GetCountRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.CountRestrictions) as CountRestrictions; - } - - /// - /// Gets Org.OData.Capabilities.V1.BatchSupported. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.BatchSupported or null. - public static BatchSupported GetBatchSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.BatchSupported) as BatchSupported; - } - - /// - /// Gets Org.OData.Capabilities.V1.SkipSupported. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.SkipSupported or null. - public static SkipSupported GetSkipSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.SkipSupported) as SkipSupported; - } - - /// - /// Gets Org.OData.Capabilities.V1.TopSupported. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.TopSupported or null. - public static TopSupported GetTopSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.TopSupported) as TopSupported; - } - - /// - /// Gets Org.OData.Capabilities.V1.KeyAsSegmentSupported. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.KeyAsSegmentSupported or null. - public static KeyAsSegmentSupported GetKeyAsSegmentSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.KeyAsSegmentSupported) as KeyAsSegmentSupported; - } - - /// - /// Gets Org.OData.Capabilities.V1.IndexableByKey. - /// - /// The Edm model. - /// The target. - /// The Org.OData.Capabilities.V1.IndexableByKey or null. - public static IndexableByKey GetIndexableByKey(this IEdmModel model, IEdmVocabularyAnnotatable target) - { - return model.GetCapabilities(target, CapabilitesTermKind.IndexableByKey) as IndexableByKey; - } - - /// - /// Create the capabiliites restriction - /// - /// The Edm model. - /// The Target. - /// The Capabiliites kind. - /// The . - public static ICapablitiesRestrictions CreateCapabilitesRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target, CapabilitesTermKind kind) - { - Debug.Assert(model != null); - Debug.Assert(target != null); - - ICapablitiesRestrictions capabilitiesRestrictions = null; - switch(kind) - { - case CapabilitesTermKind.DeleteRestrictions: // DeleteRestrictions - capabilitiesRestrictions = new DeleteRestrictions(); - break; - - case CapabilitesTermKind.UpdateRestrictions: // UpdateRestrictions - capabilitiesRestrictions = new UpdateRestrictions(); - break; - - case CapabilitesTermKind.InsertRestrictions: // InsertRestrictions - capabilitiesRestrictions = new InsertRestrictions(); - break; - - case CapabilitesTermKind.SearchRestrictions: // SearchRestrictions - capabilitiesRestrictions = new SearchRestrictions(); - break; - - case CapabilitesTermKind.ExpandRestrictions: // ExpandRestrictions - capabilitiesRestrictions = new ExpandRestrictions(); - break; - - case CapabilitesTermKind.SortRestrictions: // SortRestrictions - capabilitiesRestrictions = new SortRestrictions(); - break; - - case CapabilitesTermKind.FilterRestrictions: // FilterRestrictions - capabilitiesRestrictions = new FilterRestrictions(); - break; - - case CapabilitesTermKind.NavigationRestrictions: // NavigationRestrictions - capabilitiesRestrictions = new NavigationRestrictions(); - break; - - case CapabilitesTermKind.CountRestrictions: // CountRestrictions - capabilitiesRestrictions = new CountRestrictions(); - break; - - case CapabilitesTermKind.BatchSupported: // BatchSupported - capabilitiesRestrictions = new BatchSupported(); - break; - - case CapabilitesTermKind.SkipSupported: // SkipSupported - capabilitiesRestrictions = new SkipSupported(); - break; - - case CapabilitesTermKind.TopSupported: // TopSupported - capabilitiesRestrictions = new TopSupported(); - break; - - case CapabilitesTermKind.KeyAsSegmentSupported: // KeyAsSegmentSupported - capabilitiesRestrictions = new KeyAsSegmentSupported(); - break; - - case CapabilitesTermKind.IndexableByKey: // IndexableByKey - capabilitiesRestrictions = new IndexableByKey(); - break; - - case CapabilitesTermKind.ChangeTracking: // ChangeTracking - case CapabilitesTermKind.CrossJoinSupported: // CrossJoinSupported - case CapabilitesTermKind.CallbackSupported: // CallbackSupported - case CapabilitesTermKind.FilterFunctions: // FilterFunctions - case CapabilitesTermKind.BatchContinueOnErrorSupported: // BatchContinueOnErrorSupported - case CapabilitesTermKind.AsynchronousRequestsSupported: // AsynchronousRequestsSupported - case CapabilitesTermKind.Isolation: // Isolation - case CapabilitesTermKind.AcceptableEncodings: // AcceptableEncodings - case CapabilitesTermKind.SupportedFormats: // SupportedFormats - default: - throw Error.NotSupported(String.Format(SRResource.CapabilitiesKindNotSupported, kind)); - } - - // load the annotation value - if (!capabilitiesRestrictions.Load(model, target)) - { - return null; - } - - return capabilitiesRestrictions; - } - - /// - /// Gets the capablities from the for the given . - /// - /// The Edm model. - /// The target. - /// Thye Capabilites kind. - /// The capabilities restrictions or null. - private static ICapablitiesRestrictions GetCapabilities(this IEdmModel model, IEdmVocabularyAnnotatable target, CapabilitesTermKind kind) - { - if (model == null || target == null) - { - return null; - } - - lock (_objectLock) - { - if (!ReferenceEquals(_savedModel, model)) - { - if (_capabilitesRestrictions != null) - { - _capabilitesRestrictions.Clear(); - } - _savedModel = model; - } - - if (_capabilitesRestrictions == null) - { - _capabilitesRestrictions = new Dictionary>(); - } - - ICapablitiesRestrictions restriction; - if (_capabilitesRestrictions.TryGetValue(target, out IDictionary value)) - { - // Here means we visited target before and we are sure that the value is not null. - if (value.TryGetValue(kind, out restriction)) - { - return restriction; - } - else - { - restriction = CreateCapabilitesRestrictions(model, target, kind); - value[kind] = restriction; - return restriction; - } - } - - // It's first time to query this target, create new dictionary and restriction. - value = new Dictionary(); - _capabilitesRestrictions[target] = value; - restriction = CreateCapabilitesRestrictions(model, target, kind); - value[kind] = restriction; - return restriction; - } - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesRestrictions.cs deleted file mode 100644 index fe8c5f1..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesRestrictions.cs +++ /dev/null @@ -1,57 +0,0 @@ -// ------------------------------------------------------------ -// 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.Vocabularies; -using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Edm; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// The base class of Capabilities - /// - internal abstract class CapabilitiesRestrictions : ICapablitiesRestrictions - { - /// - /// The Capablities Kind. - /// - public abstract CapabilitesTermKind Kind { get; } - - /// - /// Load the annotation value. - /// - /// The Edm model. - /// The target. - /// True/False - public virtual bool Load(IEdmModel model, IEdmVocabularyAnnotatable target) - { - Utils.CheckArgumentNull(model, nameof(model)); - Utils.CheckArgumentNull(target, nameof(target)); - - string termQualifiedName = CapabilitiesConstants.Namespace + "." + Kind.ToString(); - IEdmVocabularyAnnotation annotation = model.GetVocabularyAnnotation(target, termQualifiedName); - if (annotation == null) - { - IEdmNavigationSource navigationSource = target as IEdmNavigationSource; - - // if not, search the entity type. - if (navigationSource != null) - { - IEdmEntityType entityType = navigationSource.EntityType(); - annotation = model.GetVocabularyAnnotation(entityType, termQualifiedName); - } - } - - return Initialize(annotation); - } - - /// - /// Initialize the capabilities with the vocabulary annotation. - /// - /// The input vocabulary annotation. - protected abstract bool Initialize(IEdmVocabularyAnnotation annotation); - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesTermKind.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesTermKind.cs deleted file mode 100644 index 9da2e3c..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CapabilitiesTermKind.cs +++ /dev/null @@ -1,163 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// The Enum kind for Capabiliites annotation - /// - internal enum CapabilitesTermKind - { - /// - /// Media types of supported formats, including format parameters - /// - SupportedFormats, - - /// - /// List of acceptable compression methods for ($batch) requests, e.g. gzip - /// - AcceptableEncodings, - - /// - /// Supports key values according to OData URL conventions - /// - IndexableByKey, - - /// - /// Supported odata.isolation levels - /// - Isolation, - - /// - /// Supports key as segment - /// - KeyAsSegmentSupported, - - /// - /// Supports $top - /// - TopSupported, - - /// - /// Supports $skip - /// - SkipSupported, - - /// - /// Service supports the asynchronous request preference - /// - AsynchronousRequestsSupported, - - /// - /// Supports $batch requests - /// - BatchSupported, - - /// - /// Service supports the continue on error preference - /// - BatchContinueOnErrorSupported, - - /// - /// List of functions supported in $filter - /// - FilterFunctions, - - /// - /// Supports callbacks for the specified protocols - /// - CallbackSupported, - - /// - /// Supports cross joins for the entity sets in this container - /// - CrossJoinSupported, - - /// - /// Change tracking capabilities of this service or entity set - /// - ChangeTracking, - - /// - /// Restrictions on /$count path suffix and $count=true system query option - /// - CountRestrictions, - - /// - /// Restrictions on navigating properties according to OData URL conventions - /// - NavigationRestrictions, - - /// - /// Restrictions on $filter expressions - /// - FilterRestrictions, - - /// - /// Restrictions on $orderby expressions - /// - SortRestrictions, - - /// - /// Restrictions on $expand expressions - /// - ExpandRestrictions, - - /// - /// Restrictions on $search expressions - /// - SearchRestrictions, - - /// - /// Restrictions on insert operations - /// - InsertRestrictions, - - /// - /// Deep Insert Support of the annotated resource (the whole service, an entity set, or a collection-valued resource - /// - DeepInsertSupport, - - /// - /// Restrictions on update operations - /// - UpdateRestrictions, - - /// - /// Deep Update Support of the annotated resource (the whole service, an entity set, or a collection-valued resource) - /// - DeepUpdateSupported, - - /// - /// Restrictions on delete operations - /// - DeleteRestrictions, - - /// - /// Describes restrictions on operations applied to collection-valued structural properties. - /// - CollectionPropertyRestrictions, - - /// - /// Restrictions for function or action operation. - /// - OperationRestrictions, - - /// - /// Restrictions for retrieving a collection of entities, retrieving a singleton instance, invoking a function - /// - ReadRestrictions, - - /// - /// Custom headers that are supported/required for the annotated resource - /// - CustomHeaders, - - /// - /// Custom query options that are supported/required for the annotated resource - /// - CustomQueryOptions - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomHeaders.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomHeaders.cs deleted file mode 100644 index 086e5c2..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomHeaders.cs +++ /dev/null @@ -1,31 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Term: Org.OData.Capabilities.V1.CustomHeaders - /// - internal class CustomHeaders : CapabilitiesRestrictions - { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.CustomHeaders; - - /// - /// Collection(Capabilities.CustomParameter) - /// - public IList Parameters { get; private set; } - - protected override bool Initialize(IEdmVocabularyAnnotation annotation) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomParameter.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomParameter.cs deleted file mode 100644 index 8382f82..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomParameter.cs +++ /dev/null @@ -1,40 +0,0 @@ -// ------------------------------------------------------------ -// 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.Capabilities -{ - /// - /// Complex type: Org.OData.Capabilities.V1.CustomParameter - /// - internal class CustomParameter - { - /// - /// Gets/sets the name of the custom parameter. - /// - public string Name { get; set; } - - /// - /// Gets/sets the description of the custom parameter. - /// - public string Description { get; set; } - - /// - /// Gets/sets the documentationURL of the custom parameter. - /// - public string DocumentationURL { get; set; } - - /// - /// Gets/sets the reuired of the custom parameter. true: parameter is required, false or not specified: parameter is optional. - /// - public bool Required { get; set; } - - /// - /// Gets the list of scopes that can provide access to the resource. - /// s - public IList Scopes { get; set; } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomQueryOptions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomQueryOptions.cs deleted file mode 100644 index d4b6f82..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CustomQueryOptions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm.Vocabularies; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Term: Org.OData.Capabilities.V1.CustomQueryOptions - /// - internal class CustomQueryOptions : CapabilitiesRestrictions - { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.CustomQueryOptions; - - /// - /// Collection(Capabilities.CustomParameter) - /// - public IList Parameters { get; private set; } - - protected override bool Initialize(IEdmVocabularyAnnotation annotation) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ICapabilitiesRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/ICapabilitiesRestrictions.cs deleted file mode 100644 index bbe03b0..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ICapabilitiesRestrictions.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ------------------------------------------------------------ -// 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.Vocabularies; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Interface for the capabilities restrictions - /// - internal interface ICapablitiesRestrictions - { - /// - /// The Capablities Kind. - /// - CapabilitesTermKind Kind { get; } - - /// - /// Load the annotation value. - /// - /// The Edm model. - /// The target. - /// True/False - bool Load(IEdmModel model, IEdmVocabularyAnnotatable target); - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ModificationQueryOptionsType.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/ModificationQueryOptionsType.cs deleted file mode 100644 index 1a973cd..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ModificationQueryOptionsType.cs +++ /dev/null @@ -1,43 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Complex type: Org.OData.Capabilities.V1.ModificationQueryOptionsType - /// - internal class ModificationQueryOptionsType - { - /// - /// Gets/sets the $expand with modification requests. - /// - public bool ExpandSupported { get; private set; } - - /// - /// Gets/sets the $select with modification requests. - /// - public bool SelectSupported { get; private set; } - - /// - /// Gets/sets the $compute with modification requests. - /// - public bool ComputeSupported { get; private set; } - - /// - /// Gets/sets the $filter with modification requests. - /// - public bool FilterSupported { get; private set; } - - /// - /// Gets/sets the $search with modification requests. - /// - public bool SearchSupported { get; private set; } - - /// - /// Gets/sets the $sort with modification requests. - /// - public bool SortSupported { get; private set; } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ReadRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/ReadRestrictions.cs deleted file mode 100644 index 870295a..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ReadRestrictions.cs +++ /dev/null @@ -1,96 +0,0 @@ -// ------------------------------------------------------------ -// 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.OData.Edm; -using Microsoft.OData.Edm.Vocabularies; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - internal abstract class ReadRestrictionsBase - { - /// - /// Get the Entities can be retrieved. - /// - public bool? Readable { get; private set; } - - /// - /// Gets the List of required scopes to invoke an action or function - /// - public PermissionType Permission { get; private set; } - - /// - /// Gets the Supported or required custom headers. - /// - public IList CustomHeaders { get; private set; } - - /// - /// Gets the Supported or required custom query options. - /// - public IList CustomQueryOptions { get; private set; } - } - - /// - /// Restrictions for retrieving an entity by key - /// - internal class ReadByKeyRestrictionsType : ReadRestrictionsBase - { - - } - - /// - /// Restrictions for retrieving an entity by key - /// - internal class ReadRestrictionsType : ReadRestrictionsBase - { - /// - /// Gets the Restrictions for retrieving an entity by key. - /// Only valid when applied to a collection. If a property of `ReadByKeyRestrictions` - /// is not specified, the corresponding property value of `ReadRestrictions` applies. - /// - public ReadByKeyRestrictionsType ReadByKeyRestrictions { get; private set; } - } - - /// - /// Org.OData.Capabilities.V1.ReadRestrictions - /// - internal class ReadRestrictions : CapabilitiesRestrictions - { - /// - /// The Term type name. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.ReadRestrictions; - - /// - /// Gets the List of required scopes to invoke an action or function. - /// - public PermissionType Permission { get; private set; } - - /// - /// Gets the Supported or required custom headers. - /// - public IList CustomHeaders { get; private set; } - - /// - /// Gets the Supported or required custom query options. - /// - public IList CustomQueryOptions { get; private set; } - - protected override bool Initialize(IEdmVocabularyAnnotation annotation) - { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; - - - return true; - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/RecordExpressionExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/RecordExpressionExtensions.cs deleted file mode 100644 index 463209d..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/RecordExpressionExtensions.cs +++ /dev/null @@ -1,144 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Common; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Extension methods for - /// - internal static class RecordExpressionExtensions - { - /// - /// Get the boolean value from the record using the given property name. - /// - /// The record expression. - /// The property name. - /// The boolean value or null. - public static bool? GetBoolean(this IEdmRecordExpression record, string propertyName) - { - Utils.CheckArgumentNull(record, nameof(record)); - Utils.CheckArgumentNull(propertyName, nameof(propertyName)); - - if (record.Properties != null) - { - IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); - if (property != null) - { - IEdmBooleanConstantExpression value = property.Value as IEdmBooleanConstantExpression; - if (value != null) - { - return value.Value; - } - } - } - - return null; - } - - /// - /// Get the Enum value from the record using the given property name. - /// - /// The output enum type. - /// The record expression. - /// The property name. - /// The Enum value or null. - public static T? GetEnum(this IEdmRecordExpression record, string propertyName) - where T : struct - { - Utils.CheckArgumentNull(record, nameof(record)); - Utils.CheckArgumentNull(propertyName, nameof(propertyName)); - - if (record.Properties != null) - { - IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); - if (property != null) - { - IEdmEnumMemberExpression value = property.Value as IEdmEnumMemberExpression; - if (value != null && value.EnumMembers != null && value.EnumMembers.Any()) - { - IEdmEnumMember member = value.EnumMembers.First(); - T result; - if (Enum.TryParse(member.Name, out result)) - { - return result; - } - } - } - } - - return null; - } - - /// - /// Get the property path from the record using the given property name. - /// - /// The record expression. - /// The property name. - /// The property path or null. - public static string GetPropertyPath(this IEdmRecordExpression record, string propertyName) - { - Utils.CheckArgumentNull(record, nameof(record)); - Utils.CheckArgumentNull(propertyName, nameof(propertyName)); - - if (record.Properties != null) - { - IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); - if (property != null) - { - IEdmPathExpression value = property.Value as IEdmPathExpression; - if (value != null) - { - return value.Path; - } - } - } - - return null; - } - - /// - /// Get the collection of property path from the record using the given property name. - /// - /// The record expression. - /// The property name. - /// The collection of property path or null. - public static IList GetCollectionPropertyPath(this IEdmRecordExpression record, string propertyName) - { - Utils.CheckArgumentNull(record, nameof(record)); - Utils.CheckArgumentNull(propertyName, nameof(propertyName)); - - if (record.Properties != null) - { - IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); - if (property != null) - { - IEdmCollectionExpression value = property.Value as IEdmCollectionExpression; - if (value != null && value.Elements != null) - { - IList properties = new List(); - foreach (var a in value.Elements.Select(e => e as IEdmPathExpression)) - { - properties.Add(a.Path); - } - - if (properties.Any()) - { - return properties; - } - } - } - } - - return null; - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SupportedRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Capabilities/SupportedRestrictions.cs deleted file mode 100644 index 6457fa3..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SupportedRestrictions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// ------------------------------------------------------------ -// 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.Vocabularies; - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Base class the supported restrictions. - /// - internal abstract class SupportedRestrictions : CapabilitiesRestrictions - { - /// - /// Get the Supported boolean value. - /// - public bool? Supported { get; protected set; } - - /// - /// Test the target supports the corresponding restriction. - /// - /// True/false. - public bool IsSupported => Supported == null || Supported.Value == true; - - protected override bool Initialize(IEdmVocabularyAnnotation annotation) - { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.BooleanConstant) - { - return false; - } - - // supported - IEdmBooleanConstantExpression boolConstant = (IEdmBooleanConstantExpression)annotation.Value; - if (boolConstant != null) - { - Supported = boolConstant.Value; - } - - return true; - } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs index 5e1d049..87230c8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Common/Utils.cs @@ -4,6 +4,7 @@ // ------------------------------------------------------------ using System; +using Microsoft.OpenApi.OData.Vocabulary; namespace Microsoft.OpenApi.OData.Common { @@ -12,6 +13,23 @@ namespace Microsoft.OpenApi.OData.Common /// public static class Utils { + /// + /// Get the term qualified name when using the type of + /// + /// The type of the term. + /// The qualified name. + public static string GetTermQualifiedName() + { + object[] attributes = typeof(T).GetCustomAttributes(typeof(TermAttribute), false); + if (attributes == null && attributes.Length == 0) + { + return null; + } + + TermAttribute term = (TermAttribute)attributes[0]; + return term.QualifiedName; + } + /// /// Upper the first character of the string. /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Core/ComplexExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Core/ComplexExampleValue.cs deleted file mode 100644 index aab2578..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Core/ComplexExampleValue.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Complex type: Org.OData.Capabilities.V1.ComplexExampleValue. - /// - internal class ComplexExampleValue : ExampleValue - { - /// - /// Gets the Example value for the custom parameter - /// - public object Value { get; private set; } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Core/EntityExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Core/EntityExampleValue.cs deleted file mode 100644 index 826e244..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Core/EntityExampleValue.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Complex type: Org.OData.Capabilities.V1.EntityExampleValue. - /// - internal class EntityExampleValue : ExampleValue - { - /// - /// Gets the Example value for the custom parameter - /// - public object Value { get; private set; } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Core/ExternalExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Core/ExternalExampleValue.cs deleted file mode 100644 index 4271fbc..0000000 --- a/src/Microsoft.OpenApi.OData.Reader/Core/ExternalExampleValue.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -namespace Microsoft.OpenApi.OData.Capabilities -{ - /// - /// Complex type: Org.OData.Capabilities.V1.ExternalExampleValue. - /// - internal class ExternalExampleValue : ExampleValue - { - /// - /// Gets the Url reference to the value in its literal format - /// - public string ExternalValue { get; set; } - } -} diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs index 1146cd3..c2a7c4c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs @@ -3,64 +3,295 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Vocabulary; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; namespace Microsoft.OpenApi.OData.Edm { /// /// Vocabulary Annotation Extension methods for /// - public static class EdmAnnotationExtensions + internal static class EdmVocabularyAnnotationExtensions { + private static IDictionary> _cachedAnnotations; + private static IEdmModel _savedModel = null; // if diffenent model, the cache will be cleaned. + private static object _objectLock = new object(); + /// - /// Gets the vocabulary annotations from a target annotatable. + /// Gets the boolean term value for the given . /// - /// The model referenced to. - /// The target Annotatable to find annotation - /// The annotations or null. - public static IEnumerable GetVocabularyAnnotations(this IEdmModel model, - IEdmVocabularyAnnotatable target, string qualifiedName) + /// The Edm model. + /// The Edm target. + /// The Term qualified name. + /// Null or the boolean value for this annotation. + public static bool? GetBoolean(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) { Utils.CheckArgumentNull(model, nameof(model)); Utils.CheckArgumentNull(target, nameof(target)); Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName)); - IEdmTerm term = model.FindTerm(qualifiedName); - if (term != null) + return GetOrAddCached(model, target, qualifiedName, () => { - return model.FindVocabularyAnnotations(target, term); - } + bool? value = null; + IEdmTerm term = model.FindTerm(qualifiedName); + if (term != null) + { + value = model.GetBoolean(target, term); + if (value != null) + { + return value; + } + else + { + // Note: Graph has a lot of annotations applied to the type, not to the navigation source. + // Here's a work around to retrieve these annotations from type if we can't find it from navigation source. + // It's the same reason for belows + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + value = model.GetBoolean(entityType, term); + } + } + } - return Enumerable.Empty(); + return value; + }); } /// - /// Gets the vocabulary annotation from a target annotatable. + /// Gets the string term value for the given . /// - /// The model referenced to. - /// The target Annotatable to find annotation - /// The annotation or null. - public static IEdmVocabularyAnnotation GetVocabularyAnnotation(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + /// The Edm model. + /// The Edm target. + /// The Term qualified name. + /// Null or the string value for this annotation. + public static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) { Utils.CheckArgumentNull(model, nameof(model)); Utils.CheckArgumentNull(target, nameof(target)); Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName)); - IEdmTerm term = model.FindTerm(qualifiedName); - if (term != null) + return GetOrAddCached(model, target, qualifiedName, () => { - IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); - if (annotation != null) + string value = null; + IEdmTerm term = model.FindTerm(qualifiedName); + if (term != null) { - return annotation; + value = model.GetString(target, term); + if (value != null) + { + return value; + } + else + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + value = model.GetString(entityType, term); + } + } } - } - return null; + return value; + }); + } + + /// + /// Gets the record value (a complex type) for the given . + /// + /// The CLR mapping type. + /// The CLR mapping type. + /// The Edm model. + /// Null or the record value (a complex type) for this annotation. + public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target) + where T : IRecord, new() + { + string qualifiedName = Utils.GetTermQualifiedName(); + return model.GetRecord(target, qualifiedName); + } + + /// + /// Gets the record value (a complex type) for the given . + /// + /// The CLR mapping type. + /// The Edm model. + /// The Edm target. + /// The Term qualified name. + /// Null or the record value (a complex type) for this annotation. + public static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + where T : IRecord, new() + { + Utils.CheckArgumentNull(model, nameof(model)); + Utils.CheckArgumentNull(target, nameof(target)); + Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName)); + + return GetOrAddCached(model, target, qualifiedName, () => + { + T value = default; + IEdmTerm term = model.FindTerm(qualifiedName); + if (term != null) + { + value = model.GetRecord(target, term); + if (value != null) + { + return value; + } + else + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + value = model.GetRecord(entityType, term); + } + } + } + + return value; + }); + } + + /// + /// Gets the collection of string term value for the given . + /// + /// The Edm model. + /// The Edm target. + /// The Term qualified name. + /// Null or the collection of string value for this annotation. + public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + { + Utils.CheckArgumentNull(model, nameof(model)); + Utils.CheckArgumentNull(target, nameof(target)); + Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName)); + + return GetOrAddCached(model, target, qualifiedName, () => + { + IEnumerable value = null; + IEdmTerm term = model.FindTerm(qualifiedName); + if (term != null) + { + value = model.GetCollection(target, term); + if (value != null) + { + return value; + } + else + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + value = model.GetCollection(entityType, term); + } + } + } + + return value; + }); + } + + /// + /// Gets the collection of record value (a complex type) for the given . + /// + /// The CLR mapping type. + /// The Edm model. + /// The Edm target. + /// Null or the colllection of record value (a complex type) for this annotation. + public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target) + where T : IRecord, new() + { + Utils.CheckArgumentNull(model, nameof(model)); + Utils.CheckArgumentNull(target, nameof(target)); + + string qualifiedName = Utils.GetTermQualifiedName(); + return GetCollection(model, target, qualifiedName); + } + + /// + /// Gets the collection of record value (a complex type) for the given . + /// + /// The CLR mapping type. + /// The Edm model. + /// The Edm target. + /// The Term qualified name. + /// Null or the colllection of record value (a complex type) for this annotation. + public static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + where T : IRecord, new() + { + Utils.CheckArgumentNull(model, nameof(model)); + Utils.CheckArgumentNull(target, nameof(target)); + Utils.CheckArgumentNull(qualifiedName, nameof(qualifiedName)); + + return GetOrAddCached(model, target, qualifiedName, () => + { + IEnumerable value = null; + IEdmTerm term = model.FindTerm(qualifiedName); + if (term != null) + { + value = model.GetCollection(target, term); + if (value != null) + { + return value; + } + else + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + value = model.GetCollection(entityType, term); + } + } + } + + return value; + }); + } + + /// + /// Create the corresponding Authorization object. + /// + /// The input record. + /// The created object. + public static IEnumerable GetAuthorizations(this IEdmModel model, IEdmVocabularyAnnotatable target) + { + Utils.CheckArgumentNull(model, nameof(model)); + Utils.CheckArgumentNull(target, nameof(target)); + + return GetOrAddCached(model, target, AuthorizationConstants.Authorizations, () => + { + IEdmTerm term = model.FindTerm(AuthorizationConstants.Authorizations); + if (term != null) + { + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection) + { + IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value; + if (collection.Elements != null) + { + return collection.Elements.Select(e => + { + Debug.Assert(e.ExpressionKind == EdmExpressionKind.Record); + + IEdmRecordExpression recordExpression = (IEdmRecordExpression)e; + Authorization auth = Authorization.CreateAuthorization(recordExpression); + return auth; + }); + } + } + } + + return null; + }); } /// @@ -83,5 +314,199 @@ namespace Microsoft.OpenApi.OData.Edm return null; } + + private static T GetOrAddCached(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName, Func createFunc) + { + if (model == null || target == null) + { + return default; + } + + lock (_objectLock) + { + if (!ReferenceEquals(_savedModel, model)) + { + if (_cachedAnnotations != null) + { + _cachedAnnotations.Clear(); + } + + _savedModel = model; + } + + if (_cachedAnnotations == null) + { + _cachedAnnotations = new Dictionary>(); + } + + object restriction; + if (_cachedAnnotations.TryGetValue(target, out IDictionary value)) + { + // Here means we visited target before and we are sure that the value is not null. + if (value.TryGetValue(qualifiedName, out restriction)) + { + T ret = (T)restriction; + return ret; + } + else + { + T ret = createFunc(); + value[qualifiedName] = ret; + return ret; + } + } + + // It's first time to query this target, create new dictionary and restriction. + value = new Dictionary(); + _cachedAnnotations[target] = value; + T newAnnotation = createFunc(); + value[qualifiedName] = newAnnotation; + return newAnnotation; + } + } + + private static bool? GetBoolean(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term) + { + Debug.Assert(model != null); + Debug.Assert(target != null); + Debug.Assert(term != null); + + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.BooleanConstant) + { + IEdmBooleanConstantExpression boolConstant = (IEdmBooleanConstantExpression)annotation.Value; + if (boolConstant != null) + { + return boolConstant.Value; + } + } + + return null; + } + + private static string GetString(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term) + { + Debug.Assert(model != null); + Debug.Assert(target != null); + Debug.Assert(term != null); + + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.StringConstant) + { + IEdmStringConstantExpression stringConstant = (IEdmStringConstantExpression)annotation.Value; + return stringConstant.Value; + } + + return null; + } + + private static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term) + { + Debug.Assert(model != null); + Debug.Assert(target != null); + Debug.Assert(term != null); + + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection) + { + IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value; + if (collection.Elements != null) + { + return collection.Elements.Select(e => ((IEdmStringConstantExpression)e).Value); + } + } + + return null; + } + + private static T GetRecord(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term) + where T : IRecord, new() + { + Debug.Assert(model != null); + Debug.Assert(target != null); + Debug.Assert(term != null); + + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Record) + { + IEdmRecordExpression recordExpression = (IEdmRecordExpression)annotation.Value; + T newRecord = new T(); + newRecord.Initialize(recordExpression); + return newRecord; + } + + return default; + } + + private static IEnumerable GetCollection(this IEdmModel model, IEdmVocabularyAnnotatable target, IEdmTerm term) + where T : IRecord, new() + { + Debug.Assert(model != null); + Debug.Assert(target != null); + Debug.Assert(term != null); + + IEdmVocabularyAnnotation annotation = model.FindVocabularyAnnotations(target, term).FirstOrDefault(); + if (annotation != null && annotation.Value != null && annotation.Value.ExpressionKind == EdmExpressionKind.Collection) + { + IEdmCollectionExpression collection = (IEdmCollectionExpression)annotation.Value; + if (collection.Elements != null) + { + return collection.Elements.Select(e => + { + Debug.Assert(e.ExpressionKind == EdmExpressionKind.Record); + + IEdmRecordExpression recordExpression = (IEdmRecordExpression)e; + T newRecord = new T(); + newRecord.Initialize(recordExpression); + return newRecord; + }); + } + } + + return null; + } + + + private static Type GetTypeInfo(string fullTypeName) where T : IRecord + { + object[] attributes = typeof(T).GetCustomAttributes(typeof(SubTypeAttribute), false); + + SubTypeAttribute subType = attributes.OfType().FirstOrDefault(s => s.FullName == fullTypeName); + if (subType == null) + { + return typeof(T); + } + + return subType.Type; +#if false + foreach (var item in collection.Elements) + { + Debug.Assert(item.ExpressionKind == EdmExpressionKind.Record); + + IEdmRecordExpression record = (IEdmRecordExpression)item; + if (record.DeclaredType == null) + { + T newRecord = new T(); + newRecord.Initialize(record); + yield return newRecord; + } + else + { + IEdmComplexType complexType = record.DeclaredType.Definition as IEdmComplexType; + Debug.Assert(complexType != null); + + string fullTypeName = complexType.FullTypeName(); + + Type subType = GetTypeInfo(fullTypeName); + + IRecord sub = Activator.CreateInstance(subType) as IRecord; + Debug.Assert(typeof(T).IsAssignableFrom(subType)); + sub.Initialize(record); + yield return (T)sub; + } + } + // return Activator.CreateInstance(subType.Type) as T2; +#endif + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs index a97d6f5..a82677c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataContext.cs @@ -6,15 +6,12 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Annotations; -using Microsoft.OpenApi.OData.Authorizations; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Generator; using Microsoft.OpenApi.OData.Operation; using Microsoft.OpenApi.OData.PathItem; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.Edm { @@ -25,8 +22,6 @@ namespace Microsoft.OpenApi.OData.Edm { private IEnumerable _allPaths; private IODataPathProvider _pathProvider; - private HttpRequestProvider _httpRequestProvider; - private AuthorizationProvider _authorizationProvider; /// /// Initializes a new instance of class. @@ -54,8 +49,6 @@ namespace Microsoft.OpenApi.OData.Edm OperationHanderProvider = new OperationHandlerProvider(); PathItemHanderProvider = new PathItemHandlerProvider(); - _authorizationProvider = new AuthorizationProvider(model); - _httpRequestProvider = new HttpRequestProvider(model); _pathProvider = new ODataPathProvider(); if (settings.EnableKeyAsSegment != null) @@ -68,10 +61,10 @@ namespace Microsoft.OpenApi.OData.Edm KeyAsSegment = false; if (model.EntityContainer != null) { - var keyAsSegment = model.GetKeyAsSegmentSupported(model.EntityContainer); + var keyAsSegment = model.GetBoolean(model.EntityContainer, CapabilitiesConstants.KeyAsSegmentSupported); if (keyAsSegment != null) { - KeyAsSegment = keyAsSegment.IsSupported; + KeyAsSegment = keyAsSegment.Value; } } } @@ -139,27 +132,6 @@ namespace Microsoft.OpenApi.OData.Edm /// public IList Tags { get; private set; } - /// - /// Find the Org.OData.Core.V1.HttpRequest for a given target. - /// - /// The target. - /// The method name. - /// The or null. - public HttpRequest FindRequest(IEdmVocabularyAnnotatable target, string method) - { - return _httpRequestProvider?.GetHttpRequest(target, method); - } - - /// - /// Gets the collections for a given target in the given Edm model. - /// - /// The Edm target. - /// The collections. - public IEnumerable GetAuthorizations(IEdmVocabularyAnnotatable target) - { - return _authorizationProvider?.GetAuthorizations(target); - } - /// /// Append tag. /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs index 3b07292..a289e8e 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/ODataTypeCastSegment.cs @@ -29,7 +29,7 @@ namespace Microsoft.OpenApi.OData.Edm public override ODataSegmentKind Kind => ODataSegmentKind.TypeCast; /// - public override string Name { get => EntityType.Name; } + public override string Name { get => EntityType.FullTypeName(); } /// public override string GetPathItemName(OpenApiConvertSettings settings) => EntityType.FullTypeName(); diff --git a/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs index e8dcbe3..f104fff 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Edm/RecordExpressionExtensions.cs @@ -9,6 +9,7 @@ using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Vocabulary; namespace Microsoft.OpenApi.OData.Edm { @@ -17,6 +18,33 @@ namespace Microsoft.OpenApi.OData.Edm /// internal static class RecordExpressionExtensions { + /// + /// Get the integer value from the record using the given property name. + /// + /// The record expression. + /// The property name. + /// The integer value or null. + public static long? GetInteger(this IEdmRecordExpression record, string propertyName) + { + Utils.CheckArgumentNull(record, nameof(record)); + Utils.CheckArgumentNull(propertyName, nameof(propertyName)); + + if (record.Properties != null) + { + IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); + if (property != null) + { + IEdmIntegerConstantExpression value = property.Value as IEdmIntegerConstantExpression; + if (value != null) + { + return value.Value; + } + } + } + + return null; + } + /// /// Gets the string value of a property in the given record expression. /// @@ -105,6 +133,35 @@ namespace Microsoft.OpenApi.OData.Edm return null; } + /// + /// Get the collection of from the record using the given property name. + /// + /// The element type. + /// The record expression. + /// The property name. + /// The element action. + /// The collection or null. + public static T GetRecord(this IEdmRecordExpression record, string propertyName) + where T : IRecord, new() + { + Utils.CheckArgumentNull(record, nameof(record)); + Utils.CheckArgumentNull(propertyName, nameof(propertyName)); + + IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); + if (property != null) + { + IEdmRecordExpression recordValue = property.Value as IEdmRecordExpression; + if (recordValue != null) + { + T a = new T(); + a.Initialize(recordValue); + return a; + } + } + + return default; + } + /// /// Get the property path from the record using the given property name. /// @@ -152,9 +209,9 @@ namespace Microsoft.OpenApi.OData.Edm if (value != null && value.Elements != null) { IList properties = new List(); - foreach (var a in value.Elements.Select(e => e as IEdmPathExpression)) + foreach (var path in value.Elements.Select(e => e as IEdmPathExpression)) { - properties.Add(a.Path); + properties.Add(path.Path); } if (properties.Any()) @@ -168,6 +225,8 @@ namespace Microsoft.OpenApi.OData.Edm return null; } + + /// /// Get the collection of from the record using the given property name. /// @@ -176,8 +235,8 @@ namespace Microsoft.OpenApi.OData.Edm /// The property name. /// The element action. /// The collection or null. - public static IList GetCollection(this IEdmRecordExpression record, string propertyName, Action elementAction) - where T: new() + public static IList GetCollection(this IEdmRecordExpression record, string propertyName, Action elementAction) + where T: class, new() { Utils.CheckArgumentNull(record, nameof(record)); Utils.CheckArgumentNull(propertyName, nameof(propertyName)); @@ -189,7 +248,7 @@ namespace Microsoft.OpenApi.OData.Edm if (collection != null && collection.Elements != null) { IList items = new List(); - foreach (var item in collection.Elements) + foreach (IEdmRecordExpression item in collection.Elements.OfType()) { T a = new T(); elementAction(a, item); @@ -258,5 +317,40 @@ namespace Microsoft.OpenApi.OData.Edm return null; } + + /// + /// Get the collection of from the record using the given property name. + /// + /// The element type. + /// The record expression. + /// The property name. + /// The element action. + /// The collection or null. + public static IList GetCollection(this IEdmRecordExpression record, string propertyName) + where T : IRecord, new() + { + Utils.CheckArgumentNull(record, nameof(record)); + Utils.CheckArgumentNull(propertyName, nameof(propertyName)); + + IEdmPropertyConstructor property = record.Properties.FirstOrDefault(e => e.Name == propertyName); + if (property != null) + { + IEdmCollectionExpression collection = property.Value as IEdmCollectionExpression; + if (collection != null && collection.Elements != null) + { + IList items = new List(); + foreach (IEdmRecordExpression item in collection.Elements.OfType()) + { + T a = new T(); + a.Initialize(item); + items.Add(a); + } + + return items; + } + } + + return null; + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs index 0c095e4..780fc58 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiParameterGenerator.cs @@ -9,9 +9,10 @@ using Microsoft.OData.Edm; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.Generator { @@ -178,8 +179,8 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(target, nameof(target)); - TopSupported top = context.Model.GetTopSupported(target); - if (top == null || top.IsSupported) + bool? top = context.Model.GetTopSupported(target); + if (top == null || top.Value) { return new OpenApiParameter { @@ -201,8 +202,8 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(target, nameof(target)); - SkipSupported skip = context.Model.GetSkipSupported(target); - if (skip == null || skip.IsSupported) + bool? skip = context.Model.GetSkipSupported(target); + if (skip == null || skip.Value) { return new OpenApiParameter { @@ -224,7 +225,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(target, nameof(target)); - SearchRestrictions search = context.Model.GetSearchRestrictions(target); + SearchRestrictionsType search = context.Model.GetRecord(target, CapabilitiesConstants.SearchRestrictions); if (search == null || search.IsSearchable) { return new OpenApiParameter @@ -247,7 +248,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(target, nameof(target)); - CountRestrictions count = context.Model.GetCountRestrictions(target); + CountRestrictionsType count = context.Model.GetRecord(target, CapabilitiesConstants.CountRestrictions); if (count == null || count.IsCountable) { return new OpenApiParameter @@ -270,7 +271,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(target, nameof(target)); - FilterRestrictions filter = context.Model.GetFilterRestrictions(target); + FilterRestrictionsType filter = context.Model.GetRecord(target, CapabilitiesConstants.FilterRestrictions); if (filter == null || filter.IsFilterable) { return new OpenApiParameter @@ -318,7 +319,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(target, nameof(target)); Utils.CheckArgumentNull(entityType, nameof(entityType)); - SortRestrictions sort = context.Model.GetSortRestrictions(target); + SortRestrictionsType sort = context.Model.GetRecord(target, CapabilitiesConstants.SortRestrictions); if (sort != null && !sort.IsSortable) { return null; @@ -407,7 +408,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(target, nameof(target)); Utils.CheckArgumentNull(entityType, nameof(entityType)); - NavigationRestrictions navigation = context.Model.GetNavigationRestrictions(target); + NavigationRestrictionsType navigation = context.Model.GetRecord(target, CapabilitiesConstants.NavigationRestrictions); if (navigation != null && !navigation.IsNavigable) { return null; @@ -486,7 +487,7 @@ namespace Microsoft.OpenApi.OData.Generator Utils.CheckArgumentNull(target, nameof(target)); Utils.CheckArgumentNull(entityType, nameof(entityType)); - ExpandRestrictions expand = context.Model.GetExpandRestrictions(target); + ExpandRestrictionsType expand = context.Model.GetRecord(target, CapabilitiesConstants.ExpandRestrictions); if (expand != null && !expand.IsExpandable) { return null; diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs index 8b78b1a..e1607ec 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecurityRequirementGenerator.cs @@ -3,11 +3,13 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System.Linq; using System.Collections.Generic; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; -using Microsoft.OpenApi.OData.Authorizations; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.Generator { @@ -47,5 +49,37 @@ namespace Microsoft.OpenApi.OData.Generator } } } + + /// + /// Create the list of object. + /// + /// The OData to Open API context. + /// The securitySchemes. + /// The created collection. + public static IEnumerable CreateSecurityRequirements(this ODataContext context, + IList permissions) + { + Utils.CheckArgumentNull(context, nameof(context)); + + if (permissions != null) + { + foreach (PermissionType permission in permissions) + { + yield return new OpenApiSecurityRequirement + { + [ + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = permission.Scheme.Authorization + } + } + ] = new List(permission.Scopes?.Select(c => c.Scope) ?? new List()) + }; + } + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs index 83ba259..f0cfb92 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Generator/OpenApiSecuritySchemeGenerator.cs @@ -8,9 +8,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Authorizations; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; namespace Microsoft.OpenApi.OData.Generator { @@ -35,7 +35,12 @@ namespace Microsoft.OpenApi.OData.Generator } IDictionary securitySchemes = new Dictionary(); - var authorizations = context.GetAuthorizations(context.EntityContainer); + var authorizations = context.Model.GetAuthorizations(context.EntityContainer); + if (authorizations == null) + { + return securitySchemes; + } + foreach (var authorization in authorizations) { OpenApiSecurityScheme scheme = new OpenApiSecurityScheme diff --git a/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs new file mode 100644 index 0000000..679a0bd --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/OData/IEdmExpressionExtensions.cs @@ -0,0 +1,137 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Properties; + +namespace Microsoft.OpenApi.OData +{ + /// + /// Extension methods for . + /// + internal static class IEdmExpressionExtensions + { + /// + /// Convert an to a + /// + /// The . + /// The null or . + public static ODataValue Convert(this IEdmExpression expression) + { + if (expression == null) + { + return null; + } + + switch (expression.ExpressionKind) + { + case EdmExpressionKind.BinaryConstant: + IEdmBinaryConstantExpression binaryConstant = (IEdmBinaryConstantExpression)expression; + return new ODataPrimitiveValue(binaryConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetBinary(false) + }; + + case EdmExpressionKind.BooleanConstant: + IEdmBooleanConstantExpression booleanConstant = (IEdmBooleanConstantExpression)expression; + return new ODataPrimitiveValue(booleanConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetBoolean(false) + }; + + case EdmExpressionKind.DateTimeOffsetConstant: + IEdmDateTimeOffsetConstantExpression dateTimeOffsetConstant = (IEdmDateTimeOffsetConstantExpression)expression; + return new ODataPrimitiveValue(dateTimeOffsetConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetDateTimeOffset(false) + }; + + case EdmExpressionKind.DecimalConstant: + IEdmDecimalConstantExpression decimalConstant = (IEdmDecimalConstantExpression)expression; + return new ODataPrimitiveValue(decimalConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetDecimal(false) + }; + + case EdmExpressionKind.FloatingConstant: + IEdmFloatingConstantExpression floatConstant = (IEdmFloatingConstantExpression)expression; + return new ODataPrimitiveValue(floatConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetDouble(false) + }; + + case EdmExpressionKind.GuidConstant: + IEdmGuidConstantExpression guidConstant = (IEdmGuidConstantExpression)expression; + return new ODataPrimitiveValue(guidConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetGuid(false) + }; + + case EdmExpressionKind.IntegerConstant: + IEdmIntegerConstantExpression integerConstant = (IEdmIntegerConstantExpression)expression; + return new ODataPrimitiveValue(integerConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetInt64(false) + }; + + case EdmExpressionKind.StringConstant: + IEdmStringConstantExpression stringConstant = (IEdmStringConstantExpression)expression; + return new ODataPrimitiveValue(stringConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetString(false) + }; + + case EdmExpressionKind.DurationConstant: + IEdmDurationConstantExpression durationConstant = (IEdmDurationConstantExpression)expression; + return new ODataPrimitiveValue(durationConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetDuration(false) + }; + + case EdmExpressionKind.TimeOfDayConstant: + IEdmTimeOfDayConstantExpression timeOfDayConstant = (IEdmTimeOfDayConstantExpression)expression; + return new ODataPrimitiveValue(timeOfDayConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetTimeOfDay(false) + }; + + case EdmExpressionKind.DateConstant: + IEdmDateConstantExpression dateConstant = (IEdmDateConstantExpression)expression; + return new ODataPrimitiveValue(dateConstant.Value) + { + TypeReference = EdmCoreModel.Instance.GetDate(false) + }; + + case EdmExpressionKind.Record: + IEdmRecordExpression recordExpression = (IEdmRecordExpression)expression; + return new ODataResourceValue + { + TypeReference = recordExpression.DeclaredType, + Properties = recordExpression.Properties.ToDictionary(p => p.Name, p => p.Value.Convert()) + }; + + case EdmExpressionKind.Collection: + IEdmCollectionExpression collectionExpression = (IEdmCollectionExpression)expression; + ODataCollectValue collectionValue = new ODataCollectValue + { + TypeReference = collectionExpression.DeclaredType + }; + + collectionValue.Elements = collectionExpression.Elements.Select(e => e.Convert()).ToList(); + return collectionValue; + + case EdmExpressionKind.Path: + case EdmExpressionKind.PropertyPath: + case EdmExpressionKind.NavigationPropertyPath: + case EdmExpressionKind.EnumMember: + default: + throw new NotSupportedException(String.Format(SRResource.NotSupportedEdmExpressionKind, expression.ExpressionKind)); + } + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/TopSupported.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs similarity index 52% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/TopSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs index d533a71..a0c27e8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/TopSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataCollectValue.cs @@ -3,16 +3,15 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +using System.Collections.Generic; + +namespace Microsoft.OpenApi.OData { /// - /// Org.OData.Capabilities.V1.TopSupported + /// Represents an OData value. /// - internal class TopSupported : SupportedRestrictions + internal class ODataCollectValue : ODataValue { - /// - /// The Term type Kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.TopSupported; + public IList Elements { get; set; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SkipSupported.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataComplexValue.cs similarity index 52% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/SkipSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataComplexValue.cs index 6a20f6f..b61bda4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SkipSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataComplexValue.cs @@ -3,16 +3,12 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData { /// - /// Org.OData.Capabilities.V1.SkipSupported + /// Represents an OData complex value. /// - internal class SkipSupported : SupportedRestrictions + internal class ODataComplexValue : ODataResourceValue { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.SkipSupported; } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/BatchSupported.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataEntityValue.cs similarity index 51% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/BatchSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataEntityValue.cs index d3c30a5..088879c 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/BatchSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataEntityValue.cs @@ -3,16 +3,12 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData { /// - /// Org.OData.Capabilities.V1.BatchSupported + /// Represents an OData entity value. /// - internal class BatchSupported : SupportedRestrictions + internal class ODataEntityValue : ODataResourceValue { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.BatchSupported; } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Core/PrimitiveExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs similarity index 50% rename from src/Microsoft.OpenApi.OData.Reader/Core/PrimitiveExampleValue.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs index bb65f14..4bab519 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Core/PrimitiveExampleValue.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataPrimitiveValue.cs @@ -3,16 +3,26 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData { /// - /// Complex type: Org.OData.Capabilities.V1.PrimitiveExampleValue. + /// Represents an OData primitive value. /// - internal class PrimitiveExampleValue : ExampleValue + internal class ODataPrimitiveValue : ODataValue { + public ODataPrimitiveValue(object value) + { + Value = value; + } + /// - /// Gets the Example value for the custom parameter + /// Gets the underlying CLR object wrapped by this . /// public object Value { get; private set; } + + public override string ToString() + { + return Value.ToString(); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/KeyAsSegmentSupported.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs similarity index 56% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/KeyAsSegmentSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs index acdbf37..c0990e0 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/KeyAsSegmentSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataResourceValue.cs @@ -3,16 +3,18 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +using System.Collections.Generic; + +namespace Microsoft.OpenApi.OData { /// - /// Org.OData.Capabilities.V1.KeyAsSegmentSupported + /// Represents an OData resource value (complex or entity). /// - internal class KeyAsSegmentSupported : SupportedRestrictions + internal class ODataResourceValue : ODataValue { /// - /// The Term type kind. + /// Gets or sets the properties. /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.KeyAsSegmentSupported; + public IDictionary Properties { get; set; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Core/ExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs similarity index 60% rename from src/Microsoft.OpenApi.OData.Reader/Core/ExampleValue.cs rename to src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs index e9a3ce1..d51c017 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Core/ExampleValue.cs +++ b/src/Microsoft.OpenApi.OData.Reader/OData/ODataValue.cs @@ -3,16 +3,18 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +using Microsoft.OData.Edm; + +namespace Microsoft.OpenApi.OData { /// - /// Complex type: Org.OData.Capabilities.V1.ExampleValue. + /// Represents an OData value. /// - internal class ExampleValue + internal abstract class ODataValue { /// - /// Gets the description of the example value. + /// Gets or set the type reference of this value. /// - public string Desciption { get; private set; } + public IEdmTypeReference TypeReference { get; set; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs index a1e9f1a..2ffbfa2 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationImportOperationHandler.cs @@ -31,8 +31,6 @@ namespace Microsoft.OpenApi.OData.Operation ODataOperationImportSegment operationImportSegment = path.LastSegment as ODataOperationImportSegment; EdmOperationImport = operationImportSegment.OperationImport; - - Request = Context.FindRequest(EdmOperationImport, OperationType.ToString()); } /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs index c8d4a0e..952d6ba 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EdmOperationOperationHandler.cs @@ -13,6 +13,7 @@ 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 { @@ -49,8 +50,6 @@ namespace Microsoft.OpenApi.OData.Operation EdmOperation = operationSegment.Operation; HasTypeCast = path.Segments.Any(s => s is ODataTypeCastSegment); - - Request = Context.FindRequest(EdmOperation, OperationType.ToString()); } /// @@ -151,5 +150,45 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + /// + protected override void SetSecurity(OpenApiOperation operation) + { + IEnumerable restrictions = Context.Model.GetCollection(EdmOperation, CapabilitiesConstants.OperationRestrictions); + if (restrictions == null || !restrictions.Any()) + { + return; + } + + // TODO: how to use the collection? + OperationRestrictionType operationRestriction = restrictions.First(); + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { operationRestriction.Permission.Scheme }).ToList(); + } + + /// + protected override void AppendCustomParameters(OpenApiOperation operation) + { + IEnumerable restrictions = Context.Model.GetCollection(EdmOperation, CapabilitiesConstants.OperationRestrictions); + if (restrictions == null || !restrictions.Any()) + { + return; + } + + // TODO: how to use the collection? + OperationRestrictionType operationRestriction = restrictions.First(); + + if (operationRestriction.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, operationRestriction.CustomHeaders, ParameterLocation.Header); + } + + if (operationRestriction.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, operationRestriction.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs index 8417e44..e72a6c9 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityDeleteOperationHandler.cs @@ -3,10 +3,13 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +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 { @@ -64,5 +67,37 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + protected override void SetSecurity(OpenApiOperation operation) + { + DeleteRestrictionsType delete = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.DeleteRestrictions); + if (delete == null || delete.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { delete.Permission.Scheme }).ToList(); + } + + protected override void AppendCustomParameters(OpenApiOperation operation) + { + DeleteRestrictionsType delete = Context.Model.GetRecord< DeleteRestrictionsType>(EntitySet, CapabilitiesConstants.DeleteRestrictions); + if (delete == null) + { + return; + } + + if (delete.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, delete.CustomHeaders, ParameterLocation.Header); + } + + if (delete.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, delete.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs index 3a39231..c1655f7 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityGetOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ using System.Collections.Generic; +using System.Linq; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Common; using Microsoft.OData.Edm; using Microsoft.OpenApi.OData.Generator; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Microsoft.OpenApi.OData.Edm; namespace Microsoft.OpenApi.OData.Operation { @@ -92,5 +95,54 @@ namespace Microsoft.OpenApi.OData.Operation 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.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { readBase.Permission.Scheme }).ToList(); + } + + protected override void AppendCustomParameters(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.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, readBase.CustomHeaders, ParameterLocation.Header); + } + + if (readBase.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, readBase.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs index 61ee3b9..a0a7fc1 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntityPatchOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ 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 { @@ -76,5 +79,37 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + protected override void SetSecurity(OpenApiOperation operation) + { + UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); + if (update == null || update.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { update.Permission.Scheme }).ToList(); + } + + protected override void AppendCustomParameters(OpenApiOperation operation) + { + UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.UpdateRestrictions); + if (update == null) + { + return; + } + + if (update.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, update.CustomHeaders, ParameterLocation.Header); + } + + if (update.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, update.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs index 1bdea0c..5b87c5b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetGetOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ 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 { @@ -158,5 +161,37 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + protected override void SetSecurity(OpenApiOperation operation) + { + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + if (read == null || read.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { read.Permission.Scheme }).ToList(); + } + + protected override void AppendCustomParameters(OpenApiOperation operation) + { + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.ReadRestrictions); + if (read == null) + { + return; + } + + if (read.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, read.CustomHeaders, ParameterLocation.Header); + } + + if (read.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, read.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs index 179b955..750d11b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetOperationHandler.cs @@ -30,8 +30,6 @@ namespace Microsoft.OpenApi.OData.Operation ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; EntitySet = navigationSourceSegment.NavigationSource as IEdmEntitySet; - - Request = Context.FindRequest(EntitySet, OperationType.ToString()); } /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs index 4c49ef5..5b6a514 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/EntitySetPostOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ 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 { @@ -102,5 +105,37 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + protected override void SetSecurity(OpenApiOperation operation) + { + InsertRestrictionsType insert = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions); + if (insert == null || insert.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { insert.Permission.Scheme }).ToList(); + } + + protected override void AppendCustomParameters(OpenApiOperation operation) + { + InsertRestrictionsType insert = Context.Model.GetRecord(EntitySet, CapabilitiesConstants.InsertRestrictions); + if (insert == null) + { + return; + } + + if (insert.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, insert.CustomQueryOptions, ParameterLocation.Query); + } + + if (insert.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, insert.CustomHeaders, ParameterLocation.Header); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs index 8f993b2..199b3f8 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandler.cs @@ -7,10 +7,10 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Annotations; 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 { @@ -68,12 +68,6 @@ namespace Microsoft.OpenApi.OData.Operation /// protected ODataPath Path { get; private set; } - /// - /// Gets/sets the . - /// That will be set in the initialize method. - /// - protected HttpRequest Request { get; set; } - /// /// Initialize the handler. /// It should be call ahead of in derived class. @@ -88,33 +82,21 @@ namespace Microsoft.OpenApi.OData.Operation /// /// The . protected virtual void SetBasicInfo(OpenApiOperation operation) - { - if (Request != null && Request.Description != null) - { - operation.Summary = Request.Description; - } - } + { } /// /// Set the security information for . /// /// The . protected virtual void SetSecurity(OpenApiOperation operation) - { - if (Request != null) - { - operation.Security = Context.CreateSecurityRequirements(Request.SecuritySchemes).ToList(); - } - } + { } /// /// Set the responses information for . /// /// The . protected virtual void SetResponses(OpenApiOperation operation) - { - AppendHttpResponses(operation); - } + { } /// /// Set the request body information for . @@ -168,91 +150,26 @@ namespace Microsoft.OpenApi.OData.Operation /// The . protected virtual void AppendCustomParameters(OpenApiOperation operation) { - if (Request == null) - { - return; - } - - if (operation.Parameters == null) - { - operation.Parameters = new List(); - } - - if (Request.CustomQueryOptions != null) - { - AppendCustomParameters(operation.Parameters, Request.CustomQueryOptions, ParameterLocation.Query); - } - - if (Request.CustomHeaders != null) - { - AppendCustomParameters(operation.Parameters, Request.CustomHeaders, ParameterLocation.Header); - } } /// - /// Set the annotation for the response. + /// Set the addition annotation for the response. /// /// The operation. /// The . protected virtual void AppendHttpResponses(OpenApiOperation operation) { - if (Request == null || Request.HttpResponses == null || !Request.HttpResponses.Any()) - { - return; - } - - foreach(var httpResponse in Request.HttpResponses) - { - if (operation.Responses.TryGetValue(httpResponse.ResponseCode, out OpenApiResponse response)) - { - if (httpResponse.Description != null) - { - response.Description = httpResponse.Description; - } - - if (httpResponse.Examples != null) - { - int index = 1; - foreach (var example in httpResponse.Examples) - { - OpenApiExample ex = new OpenApiExample - { - Description = example.Description - }; - - if (example is ExternalExample) - { - var externalExample = (ExternalExample)example; - ex.Value = new OpenApiString(externalExample.ExternalValue ?? "N/A"); - } - else - { - var inlineExample = (InlineExample)example; - ex.Value = new OpenApiString(inlineExample.InlineValue ?? "N/A"); - } - - if (ex.Description != null) - { - if (response.Content.TryGetValue(ex.Description, out OpenApiMediaType mediaType)) - { - mediaType.Examples.Add("example-" + index++, ex); - } - } - } - } - } - } } /// /// Sets the custom parameters. /// /// The parameters. - /// The custom parameters. + /// The custom parameters. /// The parameter location. - private static void AppendCustomParameters(IList parameters, IList headers, ParameterLocation location) + protected static void AppendCustomParameters(IList parameters, IList customParameters, ParameterLocation location) { - foreach (var param in headers) + foreach (var param in customParameters) { OpenApiParameter parameter = new OpenApiParameter { @@ -268,7 +185,7 @@ namespace Microsoft.OpenApi.OData.Operation if (param.DocumentationURL != null) { - parameter.Example = new OpenApiString(param.DocumentationURL?? "N/A"); + parameter.Example = new OpenApiString(param.DocumentationURL ?? "N/A"); } if (param.ExampleValues != null) @@ -282,16 +199,8 @@ namespace Microsoft.OpenApi.OData.Operation Description = example.Description }; - if (example is ExternalExample) - { - var externalExample = (ExternalExample)example; - ex.Value = new OpenApiString(externalExample.ExternalValue ?? "N/A"); - } - else - { - var inlineExample = (InlineExample)example; - ex.Value = new OpenApiString(inlineExample.InlineValue ?? "N/A"); - } + // maybe call convert to Uri literal + ex.Value = new OpenApiString(example.Value.ToString()); parameter.Examples.Add("example-" + index++, ex); } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs index 91b06e2..b1b77bb 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/OperationHandlerProvider.cs @@ -3,9 +3,9 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using System.Collections.Generic; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -using System.Collections.Generic; namespace Microsoft.OpenApi.OData.Operation { diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs index 43663a8..4d7d658 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonGetOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ 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 { @@ -92,5 +95,39 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + /// + protected override void SetSecurity(OpenApiOperation operation) + { + ReadRestrictionsType read = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions); + if (read == null || read.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { read.Permission.Scheme }).ToList(); + } + + /// + protected override void AppendCustomParameters(OpenApiOperation operation) + { + ReadRestrictionsType read = Context.Model.GetRecord(Singleton, CapabilitiesConstants.ReadRestrictions); + if (read == null) + { + return; + } + + if (read.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, read.CustomHeaders, ParameterLocation.Header); + } + + if (read.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, read.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs index 037be52..ff1b049 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonOperationHandler.cs @@ -30,8 +30,6 @@ namespace Microsoft.OpenApi.OData.Operation ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment; Singleton = navigationSourceSegment.NavigationSource as IEdmSingleton; - - Request = context.FindRequest(Singleton, OperationType.ToString()); } /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs index d88e418..9a57aad 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Operation/SingletonPatchOperationHandler.cs @@ -4,10 +4,13 @@ // ------------------------------------------------------------ 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 { @@ -76,5 +79,39 @@ namespace Microsoft.OpenApi.OData.Operation base.SetResponses(operation); } + + /// + protected override void SetSecurity(OpenApiOperation operation) + { + UpdateRestrictionsType update = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions); + if (update == null || update.Permission == null) + { + return; + } + + // the Permission should be collection, however current ODL supports the single permission. + // Will update after ODL change. + operation.Security = Context.CreateSecurityRequirements(new[] { update.Permission }).ToList(); + } + + /// + protected override void AppendCustomParameters(OpenApiOperation operation) + { + UpdateRestrictionsType update = Context.Model.GetRecord(Singleton, CapabilitiesConstants.UpdateRestrictions); + if (update == null) + { + return; + } + + if (update.CustomHeaders != null) + { + AppendCustomParameters(operation.Parameters, update.CustomHeaders, ParameterLocation.Header); + } + + if (update.CustomQueryOptions != null) + { + AppendCustomParameters(operation.Parameters, update.CustomQueryOptions, ParameterLocation.Query); + } + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs index 48e61a0..3ea823e 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntityPathItemHandler.cs @@ -4,8 +4,8 @@ // ------------------------------------------------------------ using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.PathItem { @@ -20,19 +20,22 @@ namespace Microsoft.OpenApi.OData.PathItem /// protected override void SetOperations(OpenApiPathItem item) { - IndexableByKey index = Context.Model.GetIndexableByKey(EntitySet); - if (index == null || index.IsSupported) + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet); + if (read == null || + (read.ReadByKeyRestrictions == null && read.IsReadable) || + (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.IsReadable)) { + // If we don't have Read by key read restriction, we should check the set read restrction. AddOperation(item, OperationType.Get); } - UpdateRestrictions update = Context.Model.GetUpdateRestrictions(EntitySet); + UpdateRestrictionsType update = Context.Model.GetRecord(EntitySet); if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Patch); } - DeleteRestrictions delete = Context.Model.GetDeleteRestrictions(EntitySet); + DeleteRestrictionsType delete = Context.Model.GetRecord(EntitySet); if (delete == null || delete.IsDeletable) { AddOperation(item, OperationType.Delete); diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntitySetPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntitySetPathItemHandler.cs index b75b3ad..662e2b0 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/EntitySetPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/EntitySetPathItemHandler.cs @@ -6,7 +6,7 @@ using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.PathItem { @@ -26,13 +26,13 @@ namespace Microsoft.OpenApi.OData.PathItem /// protected override void SetOperations(OpenApiPathItem item) { - NavigationRestrictions navigation = Context.Model.GetNavigationRestrictions(EntitySet); - if (navigation == null || navigation.IsNavigable) + ReadRestrictionsType read = Context.Model.GetRecord(EntitySet); + if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } - InsertRestrictions insert = Context.Model.GetInsertRestrictions(EntitySet); + InsertRestrictionsType insert = Context.Model.GetRecord(EntitySet); if (insert == null || insert.IsInsertable) { AddOperation(item, OperationType.Post); diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs index 30ea1ba..83c035b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/NavigationPropertyPathItemHandler.cs @@ -8,11 +8,11 @@ using System.Linq; using System.Collections.Generic; using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.Any; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.PathItem { @@ -49,12 +49,18 @@ namespace Microsoft.OpenApi.OData.PathItem target = NavigationSource as IEdmSingleton; } + NavigationRestrictionsType navigation = Context.Model.GetRecord(target, CapabilitiesConstants.NavigationRestrictions); + if (navigation != null && navigation.Navigability != null && navigation.Navigability.Value == NavigationType.None) + { + // This check should be done when retrieve the path, but, here is for verification. + return; + } + string navigationPropertyPath = String.Join("/", - Path.Segments.OfType().Select(e => e.NavigationProperty.Name)); + Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment)).Select(e => e.Name)); // contaiment: Get / (Post - Collection | Patch - Single) // non-containment: only Get - NavigationRestrictions navigation = Context.Model.GetNavigationRestrictions(target); if (navigation == null || !navigation.IsRestrictedProperty(navigationPropertyPath)) { AddOperation(item, OperationType.Get); @@ -67,7 +73,7 @@ namespace Microsoft.OpenApi.OData.PathItem if (LastSegmentIsKeySegment) { // Need to check this scenario is valid or not? - UpdateRestrictions update = Context.Model.GetUpdateRestrictions(target); + UpdateRestrictionsType update = Context.Model.GetRecord(target, CapabilitiesConstants.UpdateRestrictions); if (update == null || !update.IsNonUpdatableNavigationProperty(navigationPropertyPath)) { AddOperation(item, OperationType.Patch); @@ -75,7 +81,7 @@ namespace Microsoft.OpenApi.OData.PathItem } else { - InsertRestrictions insert = Context.Model.GetInsertRestrictions(target); + InsertRestrictionsType insert = Context.Model.GetRecord(target, CapabilitiesConstants.InsertRestrictions); if (insert == null || !insert.IsNonInsertableNavigationProperty(navigationPropertyPath)) { AddOperation(item, OperationType.Post); @@ -84,7 +90,7 @@ namespace Microsoft.OpenApi.OData.PathItem } else { - UpdateRestrictions update = Context.Model.GetUpdateRestrictions(target); + UpdateRestrictionsType update = Context.Model.GetRecord(target, CapabilitiesConstants.UpdateRestrictions); if (update == null || !update.IsNonUpdatableNavigationProperty(navigationPropertyPath)) { AddOperation(item, OperationType.Patch); diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationImportPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationImportPathItemHandler.cs index 7139275..43610ea 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationImportPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/OperationImportPathItemHandler.cs @@ -6,6 +6,7 @@ using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.PathItem { @@ -39,7 +40,13 @@ namespace Microsoft.OpenApi.OData.PathItem // resource path of the function import prepended with a forward slash, and whose value is a Path // Item Object containing the keyword get with an Operation Object as value that describes // how to invoke the function import. - AddOperation(item, OperationType.Get); + + // so far, + ReadRestrictionsType read = Context.Model.GetRecord(EdmOperationImport, CapabilitiesConstants.ReadRestrictions); + if (read == null || read.IsReadable) + { + AddOperation(item, OperationType.Get); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs index df7651e..a65bd82 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandler.cs @@ -81,7 +81,7 @@ namespace Microsoft.OpenApi.OData.PathItem /// /// The path item. /// The operatin type. - protected void AddOperation(OpenApiPathItem item, OperationType operationType) + protected virtual void AddOperation(OpenApiPathItem item, OperationType operationType) { IOperationHandlerProvider provider = Context.OperationHanderProvider; IOperationHandler operationHander = provider.GetHandler(Path.Kind, operationType); diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs index 9db63ad..76b124b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/PathItemHandlerProvider.cs @@ -33,7 +33,7 @@ namespace Microsoft.OpenApi.OData.PathItem // Edm OperationImport { ODataPathKind.OperationImport, new OperationImportPathItemHandler() }, - // Edm OperationImport + // Unknown { ODataPathKind.Unknown, null }, }; diff --git a/src/Microsoft.OpenApi.OData.Reader/PathItem/SingletonPathItemHandler.cs b/src/Microsoft.OpenApi.OData.Reader/PathItem/SingletonPathItemHandler.cs index cef413d..fe447b4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/PathItem/SingletonPathItemHandler.cs +++ b/src/Microsoft.OpenApi.OData.Reader/PathItem/SingletonPathItemHandler.cs @@ -5,8 +5,8 @@ using Microsoft.OData.Edm; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; namespace Microsoft.OpenApi.OData.PathItem { @@ -27,14 +27,14 @@ namespace Microsoft.OpenApi.OData.PathItem protected override void SetOperations(OpenApiPathItem item) { // Retrieve a singleton. - NavigationRestrictions navigation = Context.Model.GetNavigationRestrictions(Singleton); - if (navigation == null || navigation.IsNavigable) + ReadRestrictionsType read = Context.Model.GetRecord(Singleton); + if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } // Update a singleton - UpdateRestrictions update = Context.Model.GetUpdateRestrictions(Singleton); + UpdateRestrictionsType update = Context.Model.GetRecord(Singleton); if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Patch); diff --git a/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.Designer.cs b/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.Designer.cs index 852487e..1f368c1 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.Designer.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.OData.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class SRResource { @@ -105,6 +105,15 @@ namespace Microsoft.OpenApi.OData.Properties { } } + /// + /// Looks up a localized string similar to Not supported {0} Edm expression kind.. + /// + internal static string NotSupportedEdmExpressionKind { + get { + return ResourceManager.GetString("NotSupportedEdmExpressionKind", resourceCulture); + } + } + /// /// Looks up a localized string similar to Not supported {0} Edm type kind.. /// diff --git a/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.resx b/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.resx index fda137c..7b9ce31 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.resx +++ b/src/Microsoft.OpenApi.OData.Reader/Properties/SRResource.resx @@ -132,6 +132,9 @@ The '{0}' path item handler can't process path kind '{1}'. + + Not supported {0} Edm expression kind. + Not supported {0} Edm type kind. diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/ApiKey.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/ApiKey.cs similarity index 88% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/ApiKey.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/ApiKey.cs index 017e7f2..bfdf14e 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/ApiKey.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/ApiKey.cs @@ -7,7 +7,7 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// /// Enum type KeyLocation @@ -31,7 +31,7 @@ namespace Microsoft.OpenApi.OData.Authorizations } /// - /// Complex type 'Org.OData.Core.V1.ApiKey' + /// Complex type: 'Org.OData.Authorization.V1.ApiKey' /// internal class ApiKey : Authorization { @@ -54,10 +54,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // KeyName. KeyName = record.GetString("KeyName"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/Authorization.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Authorization.cs similarity index 90% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/Authorization.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Authorization.cs index 9825739..4c3bfb4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/Authorization.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Authorization.cs @@ -12,12 +12,13 @@ using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Properties; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Abstract complex type 'Org.OData.Core.V1.Authorization' + /// Abstract complex type: 'Org.OData.Authorization.V1.Authorization' /// - internal abstract class Authorization + [Term("Org.OData.Authorization.Authorizations")] + internal abstract class Authorization : IRecord { /// /// Name that can be used to reference the authorization flow. @@ -38,7 +39,7 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init the . /// /// The corresponding record. - public virtual void Init(IEdmRecordExpression record) + public virtual void Initialize(IEdmRecordExpression record) { Utils.CheckArgumentNull(record, nameof(record)); @@ -67,7 +68,7 @@ namespace Microsoft.OpenApi.OData.Authorizations return null; } - Authorization auth = null; + Authorization auth; switch (complexType.FullTypeName()) { case AuthorizationConstants.OpenIDConnect: // OpenIDConnect @@ -105,7 +106,7 @@ namespace Microsoft.OpenApi.OData.Authorizations if (auth != null) { - auth.Init(record); + auth.Initialize(record); } return auth; diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationConstants.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationConstants.cs similarity index 97% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationConstants.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationConstants.cs index 191b75a..cf7ccb3 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationConstants.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationConstants.cs @@ -3,7 +3,7 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// /// Constant values for Authorization Vocabulary diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationScope.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationScope.cs similarity index 84% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationScope.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationScope.cs index 6a05e2d..b42721a 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/AuthorizationScope.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/AuthorizationScope.cs @@ -7,12 +7,12 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.AuthorizationScope' + /// Complex type: 'Org.OData.Authorization.V1.AuthorizationScope' /// - internal class AuthorizationScope + internal class AuthorizationScope : IRecord { /// /// Scope name. @@ -34,7 +34,7 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init the . /// /// The corresponding record. - public virtual void Init(IEdmRecordExpression record) + public virtual void Initialize(IEdmRecordExpression record) { Utils.CheckArgumentNull(record, nameof(record)); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/Http.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Http.cs similarity index 85% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/Http.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Http.cs index 9619cae..6234b48 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/Http.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/Http.cs @@ -7,10 +7,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.Http' + /// Complex type 'Org.OData.Authorization.V1.Http' /// internal class Http : Authorization { @@ -33,10 +33,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // Scheme Scheme = record.GetString("Scheme"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2AuthCode.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2AuthCode.cs similarity index 84% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2AuthCode.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2AuthCode.cs index d473fcf..7cbf2fd 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2AuthCode.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2AuthCode.cs @@ -6,10 +6,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.OAuth2AuthCode'. + /// Complex type 'Org.OData.Authorization.V1.OAuth2AuthCode'. /// internal class OAuth2AuthCode : OAuthAuthorization { @@ -32,10 +32,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // AuthorizationUrl AuthorizationUrl = record.GetString("AuthorizationUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2ClientCredentials.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2ClientCredentials.cs similarity index 81% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2ClientCredentials.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2ClientCredentials.cs index f53be44..5cb3857 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2ClientCredentials.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2ClientCredentials.cs @@ -6,10 +6,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.OAuth2ClientCredentials' + /// Complex type 'Org.OData.Authorization.V1.OAuth2ClientCredentials' /// internal class OAuth2ClientCredentials : OAuthAuthorization { @@ -27,10 +27,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // TokenUrl TokenUrl = record.GetString("TokenUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Implicit.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Implicit.cs similarity index 82% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Implicit.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Implicit.cs index d926d54..db02422 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Implicit.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Implicit.cs @@ -6,10 +6,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.OAuth2Implicit' + /// Complex type 'Org.OData.Authorization.V1.OAuth2Implicit' /// internal class OAuth2Implicit : OAuthAuthorization { @@ -27,10 +27,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // AuthorizationUrl AuthorizationUrl = record.GetString("AuthorizationUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Password.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Password.cs similarity index 81% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Password.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Password.cs index c5a28cb..0305b74 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuth2Password.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuth2Password.cs @@ -6,10 +6,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.OAuth2Password' + /// Complex type 'Org.OData.Authorization.V1.OAuth2Password' /// internal class OAuth2Password : OAuthAuthorization { @@ -27,10 +27,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // TokenUrl TokenUrl = record.GetString("TokenUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuthAuthorization.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuthAuthorization.cs similarity index 87% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuthAuthorization.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuthAuthorization.cs index 3c32aee..73df170 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OAuthAuthorization.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OAuthAuthorization.cs @@ -8,7 +8,7 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// /// OAuth2 type kind. @@ -37,7 +37,7 @@ namespace Microsoft.OpenApi.OData.Authorizations } /// - /// Abstract complex type 'Org.OData.Core.V1.OAuthAuthorization' + /// Abstract complex type 'Org.OData.Authorization.V1.OAuthAuthorization' /// internal abstract class OAuthAuthorization : Authorization { @@ -65,13 +65,13 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // Scopes - Scopes = record.GetCollection("Scopes", (s, item) => s.Init(item as IEdmRecordExpression)); + Scopes = record.GetCollection("Scopes"); // RefreshUrl RefreshUrl = record.GetString("RefreshUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OpenIDConnect.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OpenIDConnect.cs similarity index 84% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/OpenIDConnect.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OpenIDConnect.cs index 73f064e..8ef4562 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/OpenIDConnect.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/OpenIDConnect.cs @@ -7,10 +7,10 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type 'Org.OData.Core.V1.OpenIDConnect' + /// Complex type: Org.OData.Authorization.V1.OpenIDConnect /// internal class OpenIDConnect : Authorization { @@ -29,10 +29,10 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init . /// /// the input record. - public override void Init(IEdmRecordExpression record) + public override void Initialize(IEdmRecordExpression record) { // base checked. - base.Init(record); + base.Initialize(record); // IssuerUrl IssuerUrl = record.GetString("IssuerUrl"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Authorizations/SecurityScheme.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/SecurityScheme.cs similarity index 81% rename from src/Microsoft.OpenApi.OData.Reader/Authorizations/SecurityScheme.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/SecurityScheme.cs index 8057d65..54aec31 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Authorizations/SecurityScheme.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Authorization/SecurityScheme.cs @@ -8,12 +8,13 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Authorizations +namespace Microsoft.OpenApi.OData.Vocabulary.Authorization { /// - /// Complex type Org.OData.Core.V1.SecurityScheme + /// Complex type: Org.OData.Authorization.V1.SecurityScheme /// - internal class SecurityScheme + [Term("Org.OData.Authorization.V1.SecuritySchemes")] + internal class SecurityScheme : IRecord { /// /// The name of a required authorization scheme. @@ -29,7 +30,7 @@ namespace Microsoft.OpenApi.OData.Authorizations /// Init the . /// /// The input record. - public void Init(IEdmRecordExpression record) + public void Initialize(IEdmRecordExpression record) { Utils.CheckArgumentNull(record, nameof(record)); diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs new file mode 100644 index 0000000..11d5d49 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CapabilitiesConstants.cs @@ -0,0 +1,98 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities +{ + /// + /// Term name of the Capabilities Vocabulary + /// + internal class CapabilitiesConstants + { + /// + /// Org.OData.Capabilities.V1.ReadRestrictions + /// + public const string ReadRestrictions = "Org.OData.Capabilities.V1.ReadRestrictions"; + + /// + /// Org.OData.Capabilities.V1.ChangeTracking + /// + public const string ChangeTracking = "Org.OData.Capabilities.V1.ChangeTracking"; + + /// + /// Org.OData.Capabilities.V1.FilterRestrictions + /// + public const string FilterRestrictions = "Org.OData.Capabilities.V1.FilterRestrictions"; + + /// + /// Org.OData.Capabilities.V1.SortRestrictions + /// + public const string SortRestrictions = "Org.OData.Capabilities.V1.SortRestrictions"; + + /// + /// Org.OData.Capabilities.V1.NavigationRestrictions + /// + public const string NavigationRestrictions = "Org.OData.Capabilities.V1.NavigationRestrictions"; + + /// + /// Org.OData.Capabilities.V1.SearchRestrictions + /// + public const string SearchRestrictions = "Org.OData.Capabilities.V1.SearchRestrictions"; + + /// + /// Org.OData.Capabilities.V1.CountRestrictions + /// + public const string CountRestrictions = "Org.OData.Capabilities.V1.CountRestrictions"; + + /// + /// Org.OData.Capabilities.V1.ExpandRestrictions + /// + public const string ExpandRestrictions = "Org.OData.Capabilities.V1.ExpandRestrictions"; + + /// + /// Org.OData.Capabilities.V1.DeleteRestrictions + /// + public const string DeleteRestrictions = "Org.OData.Capabilities.V1.DeleteRestrictions"; + + /// + /// Org.OData.Capabilities.V1.DeleteRestrictions + /// + public const string UpdateRestrictions = "Org.OData.Capabilities.V1.UpdateRestrictions"; + + /// + /// Org.OData.Capabilities.V1.InsertRestrictions + /// + public const string InsertRestrictions = "Org.OData.Capabilities.V1.InsertRestrictions"; + + /// + /// Org.OData.Capabilities.V1.TopSupported + /// + public const string TopSupported = "Org.OData.Capabilities.V1.TopSupported"; + + /// + /// Org.OData.Capabilities.V1.SkipSupported + /// + public const string SkipSupported = "Org.OData.Capabilities.V1.SkipSupported"; + + /// + /// Term: Org.OData.Capabilities.V1.BatchSupported + /// + public const string BatchSupported = "Org.OData.Capabilities.V1.BatchSupported"; + + /// + /// Term: rg.OData.Capabilities.V1.OperationRestrictions + /// + public const string OperationRestrictions = "Org.OData.Capabilities.V1.OperationRestrictions"; + + /// + /// Org.OData.Capabilities.V1.IndexableByKey + /// + public const string IndexableByKey = "Org.OData.Capabilities.V1.IndexableByKey"; + + /// + /// Org.OData.Capabilities.V1.KeyAsSegmentSupported + /// + public const string KeyAsSegmentSupported = "Org.OData.Capabilities.V1.KeyAsSegmentSupported"; + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CollectionPropertyRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CollectionPropertyRestrictionsType.cs similarity index 53% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/CollectionPropertyRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CollectionPropertyRestrictionsType.cs index e9da758..d125e00 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CollectionPropertyRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CollectionPropertyRestrictionsType.cs @@ -4,21 +4,18 @@ // ------------------------------------------------------------ using System.Collections.Generic; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.CollectionPropertyRestrictions + /// Complex Type: Org.OData.Capabilities.V1.CollectionPropertyRestrictionsType /// - internal class CollectionPropertyRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.CollectionPropertyRestrictions")] + internal class CollectionPropertyRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.CollectionPropertyRestrictions; - /// /// Gets the Restricted Collection-valued property. /// @@ -32,17 +29,17 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Gets Restrictions on filter expressions. /// - public FilterRestrictions FilterRestrictions { get; private set; } + public FilterRestrictionsType FilterRestrictions { get; private set; } /// /// Gets Restrictions on search expressions. /// - public SearchRestrictions SearchRestrictions { get; private set; } + public SearchRestrictionsType SearchRestrictions { get; private set; } /// /// Gets Restrictions on orderby expressions. /// - public SortRestrictions SortRestrictions { get; private set; } + public SortRestrictionsType SortRestrictions { get; private set; } /// /// Gets Supports $top. @@ -74,21 +71,46 @@ namespace Microsoft.OpenApi.OData.Capabilities /// public bool? Deletable { get; private set; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public virtual void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } + Utils.CheckArgumentNull(record, nameof(record)); - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + // CollectionProperty + CollectionProperty = record.GetPropertyPath("CollectionProperty"); + + // FilterFunctions + FilterFunctions = record.GetCollection("FilterFunctions"); + + // FilterRestrictions + FilterRestrictions = record.GetRecord("FilterRestrictions"); + + // SearchRestrictions + SearchRestrictions = record.GetRecord("SearchRestrictions"); + + // SortRestrictions + SortRestrictions = record.GetRecord("SortRestrictions"); + + // TopSupported + TopSupported = record.GetBoolean("TopSupported"); + + // SkipSupported + SkipSupported = record.GetBoolean("SkipSupported"); + + // SelectSupport + SelectSupport = record.GetRecord("SelectSupport"); + + // Insertable + Insertable = record.GetBoolean("Insertable"); + + // Updatable + Updatable = record.GetBoolean("Updatable"); // Deletable Deletable = record.GetBoolean("Deletable"); - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CountRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CountRestrictionsType.cs similarity index 78% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/CountRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CountRestrictionsType.cs index 303f8b5..fcb5d1f 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/CountRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CountRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.CountRestrictions + /// Complex Type: Org.OData.Capabilities.V1.CountRestrictionsType /// - internal class CountRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.CountRestrictions")] + internal class CountRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.CountRestrictions; - /// /// Gets the Countable value. /// @@ -63,16 +60,13 @@ namespace Microsoft.OpenApi.OData.Capabilities false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public virtual void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Countable Countable = record.GetBoolean("Countable"); @@ -82,8 +76,6 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonCountableNavigationProperties NonCountableNavigationProperties = record.GetCollectionPropertyPath("NonCountableNavigationProperties"); - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/CustomParameter.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CustomParameter.cs similarity index 58% rename from src/Microsoft.OpenApi.OData.Reader/Annotations/CustomParameter.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CustomParameter.cs index e7994da..d424326 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/CustomParameter.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/CustomParameter.cs @@ -7,44 +7,47 @@ using System.Collections.Generic; using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Core; -namespace Microsoft.OpenApi.OData.Annotations +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Complex type Org.OData.Core.V1.CustomParameter + /// Complex type: Org.OData.Capabilities.V1.CustomParameter /// - internal class CustomParameter + // [Term("Org.OData.Capabilities.V1.CustomHeaders")] + // [Term("Org.OData.Capabilities.V1.CustomQueryOptions")] + internal class CustomParameter : IRecord { /// - /// The Name. + /// Gets/sets the name of the custom parameter. /// public string Name { get; set; } /// - /// The Description. + /// Gets/sets the description of the custom parameter. /// public string Description { get; set; } /// - /// The DocumentationURL. + /// Gets/sets the documentationURL of the custom parameter. /// public string DocumentationURL { get; set; } /// - /// The Required. + /// Gets/sets the reuired of the custom parameter. true: parameter is required, false or not specified: parameter is optional. /// public bool? Required { get; set; } /// - /// The ExampleValues. - /// - public IEnumerable ExampleValues { get; set; } + /// Gets the list of scopes that can provide access to the resource. + /// s + public IList ExampleValues { get; set; } /// - /// Init the + /// Init the . /// /// The input record. - public virtual void Init(IEdmRecordExpression record) + public void Initialize(IEdmRecordExpression record) { Utils.CheckArgumentNull(record, nameof(record)); @@ -61,16 +64,7 @@ namespace Microsoft.OpenApi.OData.Annotations Required = record.GetBoolean("Required"); // ExampleValues - ExampleValues = record.GetCollection("ExampleValues", r => - { - IEdmRecordExpression itemRecord = r as IEdmRecordExpression; - if (itemRecord != null) - { - return Example.CreateExample(itemRecord); - } - - return null; - }); + ExampleValues = record.GetCollection("ExampleValues"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepInsertSupported.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepInsertSupportType.cs similarity index 55% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepInsertSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepInsertSupportType.cs index 060d9c0..3bb6f80 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepInsertSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepInsertSupportType.cs @@ -3,44 +3,41 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.DeepInsertSupport + /// Complex Type: Org.OData.Capabilities.V1.DeepInsertSupport /// - internal class DeepInsertSupported : SupportedRestrictions + [Term("Org.OData.Capabilities.V1.DeepInsertSupport")] + internal class DeepInsertSupportType : IRecord { /// - /// The Term type kind. + /// Gets Annotation target supports deep inserts /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.DeepInsertSupport; + public bool? Supported { get; private set; } /// /// Gets Annotation target supports accepting and returning nested entities annotated with the `Core.ContentID` instance annotation. /// public bool? ContentIDSupported { get; private set; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Supported Supported = record.GetBoolean("Supported"); // NonInsertableNavigationProperties ContentIDSupported = record.GetBoolean("ContentIDSupported"); - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepUpdateSupported.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepUpdateSupportType.cs similarity index 55% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepUpdateSupported.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepUpdateSupportType.cs index 2a610d7..b152ece 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeepUpdateSupported.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeepUpdateSupportType.cs @@ -3,44 +3,41 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.DeepUpdateSupported + /// Complex Type: Org.OData.Capabilities.V1.DeepUpdateSupportType /// - internal class DeepUpdateSupported : SupportedRestrictions + [Term("Org.OData.Capabilities.V1.DeepUpdateSupport")] + internal class DeepUpdateSupportType : IRecord { /// - /// The Term type kind. + /// Gets Annotation target supports deep updates /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.DeepUpdateSupported; + public bool? Supported { get; private set; } /// /// Gets Annotation target supports accepting and returning nested entities annotated with the `Core.ContentID` instance annotation. /// public bool? ContentIDSupported { get; private set; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Supported Supported = record.GetBoolean("Supported"); // NonInsertableNavigationProperties ContentIDSupported = record.GetBoolean("ContentIDSupported"); - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeleteRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeleteRestrictionsType.cs similarity index 68% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/DeleteRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeleteRestrictionsType.cs index 2d5abdd..30618dc 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/DeleteRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/DeleteRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.DeleteRestrictions + /// Complex Type: Org.OData.Capabilities.V1.DeleteRestrictionsType /// - internal class DeleteRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.DeleteRestrictions")] + internal class DeleteRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.DeleteRestrictions; - /// /// Gets the Deletable value. /// @@ -40,16 +37,16 @@ namespace Microsoft.OpenApi.OData.Capabilities /// public PermissionType Permission { get; private set; } - /// - /// Gets the Support for query options with insert requests. - /// - public ModificationQueryOptionsType QueryOptions { get; private set; } - /// /// Gets the Supported or required custom headers. /// public IList CustomHeaders { get; private set; } + /// + /// Gets the Supported or required custom query options. + /// + public IList CustomQueryOptions { get; private set; } + /// /// Test the target supports delete. /// @@ -68,16 +65,13 @@ namespace Microsoft.OpenApi.OData.Capabilities false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Deletable Deletable = record.GetBoolean("Deletable"); @@ -85,7 +79,17 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonDeletableNavigationProperties NonDeletableNavigationProperties = record.GetCollectionPropertyPath("NonDeletableNavigationProperties"); - return true; + // MaxLevels + MaxLevels = (int?)record.GetInteger("MaxLevels"); + + // Permission + Permission = record.GetRecord("Permission"); + + // CustomHeaders + CustomHeaders = record.GetCollection("CustomHeaders"); + + // CustomQueryOptions + CustomQueryOptions = record.GetCollection("CustomQueryOptions"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ExpandRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ExpandRestrictionsType.cs similarity index 71% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/ExpandRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ExpandRestrictionsType.cs index 6e9f48c..caf5ca5 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ExpandRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ExpandRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Org.OData.Capabilities.V1.ExpandRestrictions /// - internal class ExpandRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.ExpandRestrictions")] + internal class ExpandRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.ExpandRestrictions; - /// /// Gets the Expandable value. /// @@ -33,7 +30,7 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Gets the maximum number of levels that can be expanded in a expand expression. /// - public int? MaxLevles { get; private set; } + public long? MaxLevels { get; private set; } /// /// Test the target supports $expand. @@ -51,16 +48,9 @@ namespace Microsoft.OpenApi.OData.Capabilities return NonExpandableProperties != null ? NonExpandableProperties.Any(a => a == navigationPropertyPath) : false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Expandable Expandable = record.GetBoolean("Expandable"); @@ -68,7 +58,8 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonExpandableProperties NonExpandableProperties = record.GetCollectionPropertyPath("NonExpandableProperties"); - return true; + // MaxLevels + MaxLevels = record.GetInteger("MaxLevels"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterExpressionRestrictionType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterExpressionRestrictionType.cs new file mode 100644 index 0000000..a7b8ab5 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterExpressionRestrictionType.cs @@ -0,0 +1,44 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; + +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities +{ + /// + /// Complex Type: Org.OData.Capabilities.V1.FilterExpressionRestrictionType + /// + internal class FilterExpressionRestrictionType : IRecord + { + /// + /// Gets the Path to the restricted property. + /// + public string Property { get; private set; } + + /// + /// Gets the RequiresFilter value. + /// + /// + /// + public string AllowedExpressions { get; private set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Property + Property = record.GetPropertyPath("Property"); + + // AllowedExpressions + AllowedExpressions = record.GetString("AllowedExpressions"); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/FilterRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterRestrictionsType.cs similarity index 65% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/FilterRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterRestrictionsType.cs index 4632ef8..7cd05d4 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/FilterRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/FilterRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.FilterRestrictions + /// Complex Type: Org.OData.Capabilities.V1.FilterRestrictionsType /// - internal class FilterRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.FilterRestrictions")] + internal class FilterRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.FilterRestrictions; - /// /// Gets the Filterable value. /// @@ -40,6 +37,17 @@ namespace Microsoft.OpenApi.OData.Capabilities /// public IList NonFilterableProperties { get; private set; } + /// + /// Gets The maximum number of levels (including recursion) that can be traversed in a filter expression. A value of -1 indicates there is no restriction. + /// + public long? MaxLevels { get; private set; } + + /// + /// Gets These properties only allow a subset of filter expressions. + /// A valid filter expression for a single property can be enclosed in parentheses and combined by `and` with valid expressions for other properties. + /// + public IList FilterExpressionRestrictions { get; private set; } + /// /// Test the target supports filter. /// @@ -66,16 +74,13 @@ namespace Microsoft.OpenApi.OData.Capabilities return NonFilterableProperties != null ? NonFilterableProperties.Any(a => a == propertyPath) : false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Filterable Filterable = record.GetBoolean("Filterable"); @@ -89,7 +94,11 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonFilterableProperties NonFilterableProperties = record.GetCollectionPropertyPath("NonFilterableProperties"); - return true; + // MaxLevels + MaxLevels = record.GetInteger("MaxLevels"); + + // FilterExpressionRestrictions + FilterExpressionRestrictions = record.GetCollection("FilterExpressionRestrictions"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/InsertRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/InsertRestrictionsType.cs similarity index 71% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/InsertRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/InsertRestrictionsType.cs index 347c46e..3c5a7a5 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/InsertRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/InsertRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.InsertRestrictions + /// Complex Type: Org.OData.Capabilities.V1.InsertRestrictionsType /// - internal class InsertRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.InsertRestrictions")] + internal class InsertRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.InsertRestrictions; - /// /// Gets the Insertable value. /// @@ -38,7 +35,7 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Gets the maximum number of navigation properties that can be traversed. /// - public int? MaxLevels { get; private set; } + public long? MaxLevels { get; private set; } /// /// Gets the required scopes to perform the insert. @@ -78,16 +75,13 @@ namespace Microsoft.OpenApi.OData.Capabilities false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Initialize the capabilities with the vocabulary annotation. + /// + /// The input vocabulary annotation. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Insertable Insertable = record.GetBoolean("Insertable"); @@ -95,7 +89,20 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonInsertableNavigationProperties NonInsertableNavigationProperties = record.GetCollectionPropertyPath("NonInsertableNavigationProperties"); - return true; + // MaxLevels + MaxLevels = record.GetInteger("MaxLevels"); + + // Permission + Permission = record.GetRecord("Permission"); + + // QueryOptions + QueryOptions = record.GetRecord("QueryOptions"); + + // CustomHeaders + CustomHeaders = record.GetCollection("CustomHeaders"); + + // CustomHeaders + CustomQueryOptions = record.GetCollection("CustomQueryOptions"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ModificationQueryOptionsType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ModificationQueryOptionsType.cs new file mode 100644 index 0000000..51aa8c2 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ModificationQueryOptionsType.cs @@ -0,0 +1,75 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; + +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities +{ + /// + /// Complex type: Org.OData.Capabilities.V1.ModificationQueryOptionsType + /// + [Term("Org.OData.Capabilities.V1.ModificationQueryOptions")] + internal class ModificationQueryOptionsType : IRecord + { + /// + /// Gets/sets the $expand with modification requests. + /// + public bool? ExpandSupported { get; private set; } + + /// + /// Gets/sets the $select with modification requests. + /// + public bool? SelectSupported { get; private set; } + + /// + /// Gets/sets the $compute with modification requests. + /// + public bool? ComputeSupported { get; private set; } + + /// + /// Gets/sets the $filter with modification requests. + /// + public bool? FilterSupported { get; private set; } + + /// + /// Gets/sets the $search with modification requests. + /// + public bool? SearchSupported { get; private set; } + + /// + /// Gets/sets the $sort with modification requests. + /// + public bool? SortSupported { get; private set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // ExpandSupported + ExpandSupported = record.GetBoolean("ExpandSupported"); + + // SelectSupported + SelectSupported = record.GetBoolean("SelectSupported"); + + // ComputeSupported + ComputeSupported = record.GetBoolean("ComputeSupported"); + + // FilterSupported + FilterSupported = record.GetBoolean("FilterSupported"); + + // SearchSupported + SearchSupported = record.GetBoolean("SearchSupported"); + + // SortSupported + SortSupported = record.GetBoolean("SortSupported"); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/NavigationRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/NavigationRestrictionsType.cs similarity index 55% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/NavigationRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/NavigationRestrictionsType.cs index 1aa49f7..32ca4e7 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/NavigationRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/NavigationRestrictionsType.cs @@ -5,10 +5,11 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Enumerates the navigation type can apply on navigation restrictions. @@ -32,9 +33,9 @@ namespace Microsoft.OpenApi.OData.Capabilities } /// - /// Complex type name = NavigationPropertyRestriction + /// Complex Type: Org.OData.Capabilities.V1.NavigationPropertyRestriction /// - internal class NavigationPropertyRestriction + internal class NavigationPropertyRestriction : IRecord { /// /// Navigation properties can be navigated @@ -54,17 +55,17 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Restrictions on filter expressions. /// - public FilterRestrictions FilterRestrictions { get; set; } + public FilterRestrictionsType FilterRestrictions { get; set; } /// /// Restrictions on search expressions. /// - public SearchRestrictions SearchRestrictions { get; set; } + public SearchRestrictionsType SearchRestrictions { get; set; } /// /// Restrictions on orderby expressions. /// - public SortRestrictions SortRestrictions { get; set; } + public SortRestrictionsType SortRestrictions { get; set; } /// /// Supports $top. @@ -89,27 +90,27 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Restrictions on insert operations. /// - public InsertRestrictions InsertRestrictions { get; set; } + public InsertRestrictionsType InsertRestrictions { get; set; } /// /// Deep Insert Support of the annotated resource (the whole service, an entity set, or a collection-valued resource). /// - public DeepInsertSupported DeepInsertSupport { get; set; } + public DeepInsertSupportType DeepInsertSupport { get; set; } /// /// Restrictions on update operations. /// - public UpdateRestrictions UpdateRestrictions { get; set; } + public UpdateRestrictionsType UpdateRestrictions { get; set; } /// /// Deep Update Support of the annotated resource (the whole service, an entity set, or a collection-valued resource). /// - public DeepUpdateSupported DeepUpdateSupport { get; set; } + public DeepUpdateSupportType DeepUpdateSupport { get; set; } /// /// Restrictions on delete operations. /// - public DeleteRestrictions DeleteRestrictions { get; set; } + public DeleteRestrictionsType DeleteRestrictions { get; set; } /// /// Data modification (including insert) along this navigation property requires the use of ETags. @@ -119,19 +120,75 @@ namespace Microsoft.OpenApi.OData.Capabilities /// /// Restrictions for retrieving entities. /// - public ReadRestrictions ReadRestrictions { get; set; } + public ReadRestrictionsType ReadRestrictions { get; set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // NavigationProperty + NavigationProperty = record.GetPropertyPath("NavigationProperty"); // maybe call "GetNavigationPropertyPath + + // Navigability + Navigability = record.GetEnum("Navigability"); + + // FilterFunctions + FilterFunctions = record.GetCollection("FilterFunctions"); + + // FilterRestrictions + FilterRestrictions = record.GetRecord("FilterRestrictions"); + + // SearchRestrictions + SearchRestrictions = record.GetRecord("SearchRestrictions"); + + // SortRestrictions + SortRestrictions = record.GetRecord("SortRestrictions"); + + // TopSupported + TopSupported = record.GetBoolean("TopSupported"); + + // SkipSupported + SkipSupported = record.GetBoolean("SkipSupported"); + + // SelectSupport + SelectSupport = record.GetRecord("SelectSupport"); + + // IndexableByKey + IndexableByKey = record.GetBoolean("IndexableByKey"); + + // InsertRestrictions + InsertRestrictions = record.GetRecord("InsertRestrictions"); + + // DeepInsertSupport + DeepInsertSupport = record.GetRecord("DeepInsertSupport"); + + // UpdateRestrictions + UpdateRestrictions = record.GetRecord("UpdateRestrictions"); + + // DeepUpdateSupport + DeepUpdateSupport = record.GetRecord("DeepUpdateSupport"); + + // DeleteRestrictions + DeleteRestrictions = record.GetRecord("DeleteRestrictions"); + + // IndexableByKey + OptimisticConcurrencyControl = record.GetBoolean("OptimisticConcurrencyControl"); + + // ReadRestrictions + ReadRestrictions = record.GetRecord("ReadRestrictions"); + } } /// - /// Org.OData.Capabilities.V1.NavigationRestrictions + /// Complex Type: Org.OData.Capabilities.V1.NavigationRestrictionsType /// - internal class NavigationRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.NavigationRestrictions")] + internal class NavigationRestrictionsType : IRecord { - /// - /// The Term type name. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.NavigationRestrictions; - /// /// Gets the Navigability value. /// @@ -160,54 +217,19 @@ namespace Microsoft.OpenApi.OData.Capabilities false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Navigability Navigability = record.GetEnum("Navigability"); // RestrictedProperties - RestrictedProperties = GetRestrictedProperties(record); - - return true; - } - - private static IList GetRestrictedProperties(IEdmRecordExpression record) - { - if (record != null && record.Properties != null) - { - IEdmPropertyConstructor property = record.Properties.FirstOrDefault(p => p.Name == "RestrictedProperties"); - if (property != null) - { - IEdmCollectionExpression value = property.Value as IEdmCollectionExpression; - if (value != null && value.Elements != null) - { - IList restrictedProperties = new List(); - foreach (var item in value.Elements.OfType()) - { - NavigationPropertyRestriction restriction = new NavigationPropertyRestriction(); - restriction.Navigability = item.GetEnum("Navigability"); - restriction.NavigationProperty = item.GetPropertyPath("NavigationProperty"); - restrictedProperties.Add(restriction); - } - - if (restrictedProperties.Any()) - { - return restrictedProperties; - } - } - } - } - - return null; + RestrictedProperties = record.GetCollection("RestrictedProperties"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/OperationRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/OperationRestrictionType.cs similarity index 50% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/OperationRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/OperationRestrictionType.cs index 36c852c..22a155b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/OperationRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/OperationRestrictionType.cs @@ -4,21 +4,19 @@ // ------------------------------------------------------------ using System.Collections.Generic; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.OperationRestrictions + /// Complex Type: Org.OData.Capabilities.V1.OperationRestrictionType + /// Be note: in ODL 7.6, it's named as "OperationRestriction", after that, it will be changed as "OperationRestrictionType" /// - internal class OperationRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.OperationRestrictions")] + internal class OperationRestrictionType : IRecord { - /// - /// The Term type name. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.OperationRestrictions; - /// /// Gets the List of required scopes to invoke an action or function. /// @@ -34,19 +32,22 @@ namespace Microsoft.OpenApi.OData.Capabilities /// public IList CustomQueryOptions { get; private set; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } + Utils.CheckArgumentNull(record, nameof(record)); - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + // Permission + Permission = record.GetRecord("Permission"); + // CustomHeaders + CustomHeaders = record.GetCollection("CustomHeaders"); - return true; + // CustomQueryOptions + CustomQueryOptions = record.GetCollection("CustomQueryOptions"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/PermissionType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/PermissionType.cs similarity index 58% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/PermissionType.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/PermissionType.cs index 168416a..bf34363 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/PermissionType.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/PermissionType.cs @@ -4,27 +4,18 @@ // ------------------------------------------------------------ using System.Collections.Generic; -using Microsoft.OpenApi.OData.Authorizations; +using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Complex type: Org.OData.Capabilities.V1.PermissionType /// - internal class PermissionType + internal class PermissionType : IRecord { - /// - /// Initializes a new instance of class. - /// - /// The Auth flow scheme name. - /// List of scopes that can provide access to the resource. - public PermissionType(SecurityScheme scheme, IEnumerable scopes) - { - Scheme = scheme ?? throw Error.ArgumentNull(nameof(scheme)); - Scopes = scopes ?? throw Error.ArgumentNull(nameof(scopes)); - } - /// /// Gets the auth flow scheme name. /// @@ -34,5 +25,20 @@ namespace Microsoft.OpenApi.OData.Capabilities /// Gets the list of scopes that can provide access to the resource. /// public IEnumerable Scopes { get; private set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Scheme + Scheme = record.GetRecord("Scheme"); + + // Scopes + Scopes = record.GetCollection("Scopes"); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ReadRestrictionsType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ReadRestrictionsType.cs new file mode 100644 index 0000000..65aec22 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ReadRestrictionsType.cs @@ -0,0 +1,99 @@ +// ------------------------------------------------------------ +// 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.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; + +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities +{ + /// + /// Complex Type: Org.OData.Capabilities.V1.ReadRestrictionsBase + /// + internal abstract class ReadRestrictionsBase : IRecord + { + /// + /// Get the Entities can be retrieved. + /// + public bool? Readable { get; private set; } + + /// + /// Gets the List of required scopes to invoke an action or function + /// + public PermissionType Permission { get; private set; } + + /// + /// Gets the Supported or required custom headers. + /// + public IList CustomHeaders { get; private set; } + + /// + /// Gets the Supported or required custom query options. + /// + public IList CustomQueryOptions { get; private set; } + + /// + /// Test the target supports update. + /// + /// True/false. + public bool IsReadable => Readable == null || Readable.Value; + + /// + /// Init the . + /// + /// The input record. + public virtual void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Readable + Readable = record.GetBoolean("Readable"); + + // Permission + Permission = record.GetRecord("Permission"); + + // CustomHeaders + CustomHeaders = record.GetCollection("CustomHeaders"); + + // CustomQueryOptions + CustomQueryOptions = record.GetCollection("CustomQueryOptions"); + } + } + + /// + /// Complex Type: Org.OData.Capabilities.V1.ReadByKeyRestrictionsType + /// Restrictions for retrieving an entity by key + /// + internal class ReadByKeyRestrictions : ReadRestrictionsBase + { + // nothing here + } + + /// + /// Complex Type: Org.OData.Capabilities.V1.ReadRestrictionsType + /// + [Term("Org.OData.Capabilities.V1.ReadRestrictions")] + internal class ReadRestrictionsType : ReadRestrictionsBase + { + /// + /// Gets the Restrictions for retrieving an entity by key + /// + public ReadByKeyRestrictions ReadByKeyRestrictions { get; set; } + + /// + /// Init the . + /// + /// The input record. + public override void Initialize(IEdmRecordExpression record) + { + // Load base + base.Initialize(record); + + // ReadByKeyRestrictions + ReadByKeyRestrictions = record.GetRecord("ReadByKeyRestrictions"); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ScopeType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ScopeType.cs similarity index 60% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/ScopeType.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ScopeType.cs index c33dbcb..0a7d242 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/ScopeType.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/ScopeType.cs @@ -3,29 +3,17 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ +using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Complex type: Org.OData.Capabilities.V1.ScopeType /// - internal class ScopeType + internal class ScopeType : IRecord { - /// - /// Initializes a new instance of class. - /// - /// The non-nullable scope name. - /// - /// The non-nullable of the comma-separated string value of all properties - /// that will be included or excluded when using the scope - /// - public ScopeType(string scope, string restrictedProperties) - { - Scope = scope ?? throw Error.ArgumentNull(nameof(scope)); - RestrictedProperties = restrictedProperties ?? throw Error.ArgumentNull(nameof(scope)); - } - /// /// Gets the names of the scope. /// @@ -37,5 +25,20 @@ namespace Microsoft.OpenApi.OData.Capabilities /// Possible string value identifiers when specifying properties are '*', _PropertyName_, '-'_PropertyName_. /// public string RestrictedProperties { get; private set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Scope + Scope = record.GetString("Scope"); + + // RestrictedProperties + RestrictedProperties = record.GetString("RestrictedProperties"); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SearchRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SearchRestrictionsType.cs similarity index 82% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/SearchRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SearchRestrictionsType.cs index 2a39407..e001f52 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SearchRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SearchRestrictionsType.cs @@ -4,11 +4,12 @@ // ------------------------------------------------------------ using System; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Vocabularies; using System.Linq; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Common; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Enumerates the search expressions. @@ -48,15 +49,11 @@ namespace Microsoft.OpenApi.OData.Capabilities } /// - /// Org.OData.Capabilities.V1.SearchRestrictions + /// Complex Type: Org.OData.Capabilities.V1.SearchRestrictionsType /// - internal class SearchRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.SearchRestrictions")] + internal class SearchRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.SearchRestrictions; - /// /// Gets the Searchable value. /// @@ -93,16 +90,13 @@ namespace Microsoft.OpenApi.OData.Capabilities return false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Searchable Searchable = record.GetBoolean("Searchable"); @@ -131,8 +125,6 @@ namespace Microsoft.OpenApi.OData.Capabilities } } } - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SelectSupportType.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SelectSupportType.cs similarity index 57% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/SelectSupportType.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SelectSupportType.cs index 1317185..2deff9d 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SelectSupportType.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SelectSupportType.cs @@ -3,12 +3,17 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -namespace Microsoft.OpenApi.OData.Capabilities +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; + +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// /// Complex type: Org.OData.Capabilities.V1.SelectSupportType /// - internal class SelectSupportType + [Term("Org.OData.Capabilities.V1.SelectSupport")] + internal class SelectSupportType : IRecord { /// /// Gets the Supports $select. @@ -54,5 +59,41 @@ namespace Microsoft.OpenApi.OData.Capabilities /// Gets the orderby within $select is supported. /// public bool? Sortable { get; private set; } + + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Supported + Supported = record.GetBoolean("Supported"); + + // Expandable + Expandable = record.GetBoolean("Expandable"); + + // Filterable + Filterable = record.GetBoolean("Filterable"); + + // Searchable + Searchable = record.GetBoolean("Searchable"); + + // TopSupported + TopSupported = record.GetBoolean("TopSupported"); + + // SkipSupported + SkipSupported = record.GetBoolean("SkipSupported"); + + // ComputeSupported + ComputeSupported = record.GetBoolean("ComputeSupported"); + + // Countable + Countable = record.GetBoolean("Countable"); + + // Sortable + Sortable = record.GetBoolean("Sortable"); + } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SortRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SortRestrictionsType.cs similarity index 81% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/SortRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SortRestrictionsType.cs index c9ad7dc..3559341 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/SortRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/SortRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.SortRestrictions + /// Complex Type: Org.OData.Capabilities.V1.SortRestrictionsType /// - internal class SortRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.SortRestrictions")] + internal class SortRestrictionsType : IRecord { - /// - /// The Term type name. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.SortRestrictions; - /// /// Gets the Sortable value. /// @@ -75,16 +72,13 @@ namespace Microsoft.OpenApi.OData.Capabilities return NonSortableProperties != null ? NonSortableProperties.Any(a => a == propertyPath) : false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Sortable Sortable = record.GetBoolean("Sortable"); @@ -97,8 +91,6 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonSortablePropeties NonSortableProperties = record.GetCollectionPropertyPath("NonSortableProperties"); - - return true; } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/UpdateRestrictions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/UpdateRestrictionsType.cs similarity index 71% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/UpdateRestrictions.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/UpdateRestrictionsType.cs index dd9c79e..e22ac9b 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/UpdateRestrictions.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Capabilities/UpdateRestrictionsType.cs @@ -5,21 +5,18 @@ using System.Collections.Generic; using System.Linq; -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary.Capabilities { /// - /// Org.OData.Capabilities.V1.UpdateRestrictionsType + /// Complex Type: Org.OData.Capabilities.V1.UpdateRestrictionsType /// - internal class UpdateRestrictions : CapabilitiesRestrictions + [Term("Org.OData.Capabilities.V1.UpdateRestrictions")] + internal class UpdateRestrictionsType : IRecord { - /// - /// The Term type kind. - /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.UpdateRestrictions; - /// /// Gets the Updatable value, if true, entities can be updated. /// The default value is true; @@ -35,7 +32,7 @@ namespace Microsoft.OpenApi.OData.Capabilities /// Gets the maximum number of navigation properties that can be traversed when addressing the collection or entity to update. /// A value of -1 indicates there is no restriction. /// - public int MaxLevels { get; private set; } = -1; + public long? MaxLevels { get; private set; } /// /// Gets/sets the required scopes to perform update. @@ -75,16 +72,13 @@ namespace Microsoft.OpenApi.OData.Capabilities false; } - protected override bool Initialize(IEdmVocabularyAnnotation annotation) + /// + /// Init the . + /// + /// The input record. + public void Initialize(IEdmRecordExpression record) { - if (annotation == null || - annotation.Value == null || - annotation.Value.ExpressionKind != EdmExpressionKind.Record) - { - return false; - } - - IEdmRecordExpression record = (IEdmRecordExpression)annotation.Value; + Utils.CheckArgumentNull(record, nameof(record)); // Updatable Updatable = record.GetBoolean("Updatable"); @@ -92,7 +86,20 @@ namespace Microsoft.OpenApi.OData.Capabilities // NonUpdatableNavigationProperties NonUpdatableNavigationProperties = record.GetCollectionPropertyPath("NonUpdatableNavigationProperties"); - return true; + // MaxLevels + MaxLevels = record.GetInteger("MaxLevels"); + + // Permission + Permission = record.GetRecord("Permission"); + + // QueryOptions + QueryOptions = record.GetRecord("QueryOptions"); + + // CustomHeaders + CustomHeaders = record.GetCollection("CustomHeaders"); + + // CustomQueryOptions + CustomQueryOptions = record.GetCollection("CustomQueryOptions"); } } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ComplexExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ComplexExampleValue.cs new file mode 100644 index 0000000..8170fa4 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ComplexExampleValue.cs @@ -0,0 +1,14 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +namespace Microsoft.OpenApi.OData.Vocabulary.Core +{ + /// + /// Complex type: Org.OData.Core.V1.ComplexExampleValue. + /// + internal class ComplexExampleValue : ResourceExampleValue + { + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/EntityExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/EntityExampleValue.cs new file mode 100644 index 0000000..3c0006e --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/EntityExampleValue.cs @@ -0,0 +1,14 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +namespace Microsoft.OpenApi.OData.Vocabulary.Core +{ + /// + /// Complex type: Org.OData.Core.V1.EntityExampleValue. + /// + internal class EntityExampleValue : ResourceExampleValue + { + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExampleValue.cs new file mode 100644 index 0000000..e0f7b20 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExampleValue.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 Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; + +namespace Microsoft.OpenApi.OData.Vocabulary.Core +{ + /// + /// Complex type: Org.OData.Core.V1.ExampleValue. + /// + internal class ExampleValue : IRecord + { + /// + /// Gets the description of the example value. + /// + public string Description { get; private set; } + + /// + /// Init the + /// + /// The input record. + public virtual void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + // Description + Description = record.GetString("Description"); + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Annotations/ExternalExample.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExternalExampleValue.cs similarity index 57% rename from src/Microsoft.OpenApi.OData.Reader/Annotations/ExternalExample.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExternalExampleValue.cs index b9bde4b..5afceef 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Annotations/ExternalExample.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ExternalExampleValue.cs @@ -6,25 +6,26 @@ using Microsoft.OData.Edm.Vocabularies; using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Annotations +namespace Microsoft.OpenApi.OData.Vocabulary.Core { /// - /// Complex type Org.OData.Core.V1.ExternalExample + /// Complex type: Org.OData.Core.V1.ExternalExampleValue. /// - internal class ExternalExample : Example + internal class ExternalExampleValue : ExampleValue { /// - /// ExternalValue + /// Gets the Url reference to the value in its literal format /// public string ExternalValue { get; set; } /// - /// Init the . + /// Init the /// - /// The record. - public override void Init(IEdmRecordExpression record) + /// The input record. + public override void Initialize(IEdmRecordExpression record) { - base.Init(record); + // Load ExampleValue + base.Initialize(record); // ExternalValue ExternalValue = record.GetString("ExternalValue"); diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/PrimitiveExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/PrimitiveExampleValue.cs new file mode 100644 index 0000000..c91a87c --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/PrimitiveExampleValue.cs @@ -0,0 +1,49 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; + +namespace Microsoft.OpenApi.OData.Vocabulary.Core +{ + /// + /// Complex type: Org.OData.Core.V1.PrimitiveExampleValue. + /// + internal class PrimitiveExampleValue : ExampleValue + { + /// + /// Gets the Example value for the custom parameter + /// + public ODataPrimitiveValue Value { get; private set; } + + /// + /// Init the + /// + /// The input record. + public override void Initialize(IEdmRecordExpression record) + { + Utils.CheckArgumentNull(record, nameof(record)); + + /* Should we throw exception if the input record is not a primitive example value? + * Leave the below codes for further decision. + if (record.DeclaredType == null || record.DeclaredType.FullName() != "Org.OData.Core.V1.PrimitiveExampleValue") + { + throw new OpenApiException(); + } + */ + + // Load ExampleValue + base.Initialize(record); + + // Value of PrimitiveExampleValue + IEdmPropertyConstructor property = record.FindProperty("Value"); + if (property != null) + { + Value = property.Value.Convert() as ODataPrimitiveValue; + } + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ResourceExampleValue.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ResourceExampleValue.cs new file mode 100644 index 0000000..bc7c40d --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/Core/ResourceExampleValue.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.OData.Edm; +using Microsoft.OData.Edm.Vocabularies; + +namespace Microsoft.OpenApi.OData.Vocabulary.Core +{ + /// + /// Base class for and . + /// + internal abstract class ResourceExampleValue : ExampleValue + { + /// + /// Gets the Example value for the custom parameter + /// + public ODataResourceValue Value { get; private set; } + + /// + /// Init the + /// + /// The input record. + public override void Initialize(IEdmRecordExpression record) + { + // Load ExampleValue + base.Initialize(record); + + // Value of PrimitiveExampleValue + IEdmPropertyConstructor property = record.FindProperty("Value"); + if (property != null) + { + Value = property.Value.Convert() as ODataResourceValue; + } + } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Capabilities/IndexableByKey.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/IRecord.cs similarity index 56% rename from src/Microsoft.OpenApi.OData.Reader/Capabilities/IndexableByKey.cs rename to src/Microsoft.OpenApi.OData.Reader/Vocabulary/IRecord.cs index 2f6e2be..f4b6b70 100644 --- a/src/Microsoft.OpenApi.OData.Reader/Capabilities/IndexableByKey.cs +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/IRecord.cs @@ -3,19 +3,19 @@ // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------ -using Microsoft.OData.Edm; using Microsoft.OData.Edm.Vocabularies; -namespace Microsoft.OpenApi.OData.Capabilities +namespace Microsoft.OpenApi.OData.Vocabulary { /// - /// Org.OData.Capabilities.V1.IndexableByKey + /// The interface for /// - internal class IndexableByKey : SupportedRestrictions + internal interface IRecord { /// - /// The Term type kind. + /// Initialize the instance using . /// - public override CapabilitesTermKind Kind => CapabilitesTermKind.IndexableByKey; + /// The Edm record expression. + void Initialize(IEdmRecordExpression record); } } diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/TermAttribute.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/TermAttribute.cs new file mode 100644 index 0000000..2d5feb8 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/TermAttribute.cs @@ -0,0 +1,52 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace Microsoft.OpenApi.OData.Vocabulary +{ + /// + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class TermAttribute : Attribute + { + public TermAttribute(string qualifiedName) + { + QualifiedName = qualifiedName ?? throw new ArgumentNullException(nameof(qualifiedName)); + } + + public string QualifiedName { get; } + } + + /// + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] + internal class SubTypeAttribute : Attribute + { + public SubTypeAttribute(params KeyValuePair[] typeInfos) + { + SubTypes = new Dictionary(); + foreach (KeyValuePair item in typeInfos) + { + SubTypes.Add(item); + } + } + + public SubTypeAttribute(string fullTypeName, Type type) + { + FullName = fullTypeName ?? throw new ArgumentNullException(nameof(fullTypeName)); + Type = type ?? throw new ArgumentNullException(nameof(type)); + } + + public string FullName { get; } + + public Type Type { get; } + + public IDictionary SubTypes { get; } + } +} diff --git a/src/Microsoft.OpenApi.OData.Reader/Vocabulary/VocabularyAnnotationsExtensions.cs b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/VocabularyAnnotationsExtensions.cs new file mode 100644 index 0000000..e16b9d6 --- /dev/null +++ b/src/Microsoft.OpenApi.OData.Reader/Vocabulary/VocabularyAnnotationsExtensions.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.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; + +namespace Microsoft.OpenApi.OData.Vocabulary +{ + /// + /// Constant values for Vocabulary + /// + internal static class VocabularyAnnotationsExtensions + { + /// + /// Gets Org.OData.Capabilities.V1.SearchRestrictions. + /// + /// The Edm model. + /// The target. + /// The Org.OData.Capabilities.V1.SearchRestrictions or null. + public static T GetRestrictions(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + where T : IRecord, new() + { + return model.GetRestrictionsImpl(target, qualifiedName); + } + + /// + /// Gets Org.OData.Capabilities.V1.TopSupported. + /// + /// The Edm model. + /// The target. + /// The Org.OData.Capabilities.V1.TopSupported or null. + public static bool? GetTopSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) + { + return GetSupported(model, target, CapabilitiesConstants.TopSupported); + } + + /// + /// Gets Org.OData.Capabilities.V1.SkipSupported. + /// + /// The Edm model. + /// The target. + /// The Org.OData.Capabilities.V1.SkipSupported or null. + public static bool? GetSkipSupported(this IEdmModel model, IEdmVocabularyAnnotatable target) + { + return GetSupported(model, target, CapabilitiesConstants.SkipSupported); + } + + private static bool? GetSupported(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + { + bool? supported = model.GetBoolean(target, qualifiedName); + if (supported == null) + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + + // if not, search the entity type. + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + supported = model.GetBoolean(entityType, qualifiedName); + } + } + + return supported; + } + + private static T GetRestrictionsImpl(this IEdmModel model, IEdmVocabularyAnnotatable target, string qualifiedName) + where T : IRecord, new() + { + T restrictions = model.GetRecord(target, qualifiedName); + if (restrictions == null) + { + IEdmNavigationSource navigationSource = target as IEdmNavigationSource; + + // if not, search the entity type. + if (navigationSource != null) + { + IEdmEntityType entityType = navigationSource.EntityType(); + restrictions = model.GetRecord(entityType, qualifiedName); + } + } + + return restrictions; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestProviderTests.cs deleted file mode 100644 index da20ba9..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestProviderTests.cs +++ /dev/null @@ -1,308 +0,0 @@ -// ------------------------------------------------------------ -// 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 System.Xml.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Annotations; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Annotations.Tests -{ - public class HttpRequestProviderTests - { - [Fact] - public void CtorThrowArgumentNullModel() - { - // Arrange & Act & Assert - Assert.Throws("model", () => new HttpRequestProvider(model: null)); - } - - [Fact] - public void GetHttpRequestThrowArgumentNullTarget() - { - // Arrange & Act & Assert - Assert.Throws("target", - () => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(target: null, method: "GET")); - } - - [Fact] - public void GetHttpRequestThrowArgumentNullMethod() - { - // Arrange & Act & Assert - Assert.Throws("method", - () => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(new EdmEntityContainer("NS", "Default"), method: null)); - } - - [Theory] - [InlineData("Customers")] - [InlineData("Me")] - public void GetHttpRequestsReturnsNullForTargetWithoutAnnotations(string name) - { - // Arrange - IEdmModel model = GetEdmModel("", ""); - var httpRequestProvider = new HttpRequestProvider(model); - IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name); - Assert.NotNull(navigationSource); - - // Act & Assert - var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.Null(requests); - } - - [Theory] - [InlineData("Customers")] - [InlineData("Me")] - public void GetHttpRequestsReturnsForEdmModelNavigationSourceWithAnnotations(string name) - { - // Arrange - string annotation = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.AccessAsUser.All - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.Read.All - Directory.ReadWrite.All - Directory.AccessAsUser.All - - - - - - - - Device.ReadWrite.All - Directory.Read.All - Directory.ReadWrite.All - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.ReadWrite.All - Directory.AccessAsUser.All - - - - - - - - "; - - IEdmModel model = GetEdmModel(annotation, annotation); - var httpRequestProvider = new HttpRequestProvider(model); - - IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name); - Assert.NotNull(navigationSource); - - // Act - var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.NotEmpty(requests); - Assert.Equal(3, requests.Count()); - - // Act - var anotherRequests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.True(ReferenceEquals(requests, anotherRequests)); - - // Act (PATCH) - var request = httpRequestProvider.GetHttpRequest(navigationSource as IEdmVocabularyAnnotatable, "PATCH"); - - // Assert - Assert.NotNull(request); - Assert.Equal("PATCH Example", request.MethodDescription); - Assert.NotNull(request.SecuritySchemes); - var securityScheme = Assert.Single(request.SecuritySchemes); - Assert.Equal("Delegated (work or school account)", securityScheme.Authorization); - Assert.NotNull(securityScheme.RequiredScopes); - Assert.Equal(new[] { "Directory.ReadWrite.All", "Directory.AccessAsUser.All" }, securityScheme.RequiredScopes); - } - - private static IEdmModel GetEdmModel(string entitySetAnnotation, string singletonAnnotation) - { - string template = @" - - - - - - - - - - - - {0} - - - {1} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - string modelText = string.Format(template, entitySetAnnotation, singletonAnnotation); - - return CsdlReader.Parse(XElement.Parse(modelText).CreateReader()); - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestTests.cs deleted file mode 100644 index 46b6114..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Annotations/HttpRequestTests.cs +++ /dev/null @@ -1,310 +0,0 @@ -// ------------------------------------------------------------ -// 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 System.Xml.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Annotations; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Annotations.Tests -{ - public class HttpRequestTests - { -#if false - [Fact] - public void CtorThrowArgumentNullModel() - { - // Arrange & Act & Assert - Assert.Throws("model", () => new HttpRequestProvider(model: null)); - } - - [Fact] - public void GetHttpRequestThrowArgumentNullTarget() - { - // Arrange & Act & Assert - Assert.Throws("target", - () => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(target: null, method: "GET")); - } - - [Fact] - public void GetHttpRequestThrowArgumentNullMethod() - { - // Arrange & Act & Assert - Assert.Throws("method", - () => new HttpRequestProvider(EdmCoreModel.Instance).GetHttpRequest(new EdmEntityContainer("NS", "Default"), method: null)); - } - - [Theory] - [InlineData("Customers")] - [InlineData("Me")] - public void GetHttpRequestsReturnsNullForTargetWithoutAnnotations(string name) - { - // Arrange - IEdmModel model = GetEdmModel("", ""); - var httpRequestProvider = new HttpRequestProvider(model); - IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name); - Assert.NotNull(navigationSource); - - // Act & Assert - var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.Null(requests); - } - - [Theory] - [InlineData("Customers")] - [InlineData("Me")] - public void GetHttpRequestsReturnsForEdmModelNavigationSourceWithAnnotations(string name) - { - // Arrange - string annotation = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.AccessAsUser.All - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.Read.All - Directory.ReadWrite.All - Directory.AccessAsUser.All - - - - - - - - Device.ReadWrite.All - Directory.Read.All - Directory.ReadWrite.All - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory.ReadWrite.All - Directory.AccessAsUser.All - - - - - - - - "; - - IEdmModel model = GetEdmModel(annotation, annotation); - var httpRequestProvider = new HttpRequestProvider(model); - - IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name); - Assert.NotNull(navigationSource); - - // Act - var requests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.NotEmpty(requests); - Assert.Equal(3, requests.Count()); - - // Act - var anotherRequests = httpRequestProvider.GetHttpRequests(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.True(ReferenceEquals(requests, anotherRequests)); - - // Act (PATCH) - var request = httpRequestProvider.GetHttpRequest(navigationSource as IEdmVocabularyAnnotatable, "PATCH"); - - // Assert - Assert.NotNull(request); - Assert.Equal("PATCH Example", request.MethodDescription); - Assert.NotNull(request.SecuritySchemes); - var securityScheme = Assert.Single(request.SecuritySchemes); - Assert.Equal("Delegated (work or school account)", securityScheme.Authorization); - Assert.NotNull(securityScheme.RequiredScopes); - Assert.Equal(new[] { "Directory.ReadWrite.All", "Directory.AccessAsUser.All" }, securityScheme.RequiredScopes); - } - - private static IEdmModel GetEdmModel(string entitySetAnnotation, string singletonAnnotation) - { - string template = @" - - - - - - - - - - - - {0} - - - {1} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - string modelText = string.Format(template, entitySetAnnotation, singletonAnnotation); - - return CsdlReader.Parse(XElement.Parse(modelText).CreateReader()); - } -#endif - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Authorizations/AuthorizationProviderTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Authorizations/AuthorizationProviderTests.cs deleted file mode 100644 index d03368c..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Authorizations/AuthorizationProviderTests.cs +++ /dev/null @@ -1,130 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OData.Edm.Validation; -using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Authorizations; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Authorizations.Tests -{ - public class AuthorizationProviderTests - { - [Fact] - public void CtroThrowArgumentNullModel() - { - // Arrange & Act & Assert - Assert.Throws("model", () => new AuthorizationProvider(model: null)); - } - - [Fact] - public void GetAuthorizationsThrowArgumentNullTarget() - { - // Arrange & Act & Assert - Assert.Throws("target", - () => new AuthorizationProvider(EdmCoreModel.Instance).GetAuthorizations(target: null)); - } - - [Fact] - public void GetAuthorizationsReturnsNullForTargetWithoutAuthorization() - { - // Arrange - EdmModel model = new EdmModel(); - EdmEntityContainer container = new EdmEntityContainer("NS", "Container"); - model.AddElement(container); - AuthorizationProvider provider = new AuthorizationProvider(model); - - // Act & Assert - var authorizations = provider.GetAuthorizations(container); - - // Assert - Assert.Empty(authorizations); - } - - [Theory] - [InlineData("Entities")] - [InlineData("Me")] - public void GetAuthorizationsReturnsForEdmModelNavigationSourceWithAuthroizations(string name) - { - // Arrange - IEdmModel model = GetEdmModel(); - IEdmNavigationSource navigationSource = model.FindDeclaredNavigationSource(name); - Assert.NotNull(navigationSource); - AuthorizationProvider provider = new AuthorizationProvider(model); - - // Act - var authorizations = provider.GetAuthorizations(navigationSource as IEdmVocabularyAnnotatable); - - // Assert - Assert.NotEmpty(authorizations); - Assert.Equal(2, authorizations.Count()); - Assert.IsType(authorizations.First()); - Assert.IsType(authorizations.Last()); - } - - private static IEdmModel GetEdmModel() - { - const string schema = @" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - - IEdmModel parsedModel; - IEnumerable errors; - bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out parsedModel, out errors); - Assert.True(parsed); - return parsedModel; - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CountRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CountRestrictionsTests.cs deleted file mode 100644 index c8c6b06..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CountRestrictionsTests.cs +++ /dev/null @@ -1,149 +0,0 @@ -// ------------------------------------------------------------ -// 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 Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class CountRestrictionsTests - { - [Fact] - public void KindPropertyReturnsCountRestrictionEnumMember() - { - // Arrange & Act - CountRestrictions count = new CountRestrictions(); - - // Assert - Assert.Equal(CapabilitesTermKind.CountRestrictions, count.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultPropertyValues() - { - // Arrange & Act - CountRestrictions count = new CountRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = count.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(count.IsCountable); - Assert.Null(count.Countable); - Assert.Null(count.NonCountableProperties); - Assert.Null(count.NonCountableNavigationProperties); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectCountRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - CountRestrictions count = new CountRestrictions(); - bool result = count.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyCountRestrictions(count); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectCountRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - CountRestrictions count = new CountRestrictions(); - bool result = count.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyCountRestrictions(count); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @" - - - - - - Emails - mij - - - - - RelatedEvents - abc - - - - "; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - - private static void VerifyCountRestrictions(CountRestrictions count) - { - Assert.NotNull(count); - - Assert.NotNull(count.Countable); - Assert.False(count.Countable.Value); - Assert.False(count.IsCountable); - - Assert.NotNull(count.NonCountableProperties); - Assert.Equal(2, count.NonCountableProperties.Count); - Assert.Equal("Emails|mij", String.Join("|", count.NonCountableProperties)); - - Assert.NotNull(count.NonCountableNavigationProperties); - Assert.Equal(2, count.NonCountableNavigationProperties.Count); - Assert.Equal("RelatedEvents,abc", String.Join(",", count.NonCountableNavigationProperties)); - - Assert.False(count.IsNonCountableProperty("id")); - Assert.True(count.IsNonCountableProperty("Emails")); - Assert.True(count.IsNonCountableNavigationProperty("RelatedEvents")); - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/DeleteRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/DeleteRestrictionsTests.cs deleted file mode 100644 index d74d4c3..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/DeleteRestrictionsTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -// ------------------------------------------------------------ -// 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 Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class DeleteRestrictionsTests - { - [Fact] - public void KindPropertyReturnsDeleteRestrictionsEnumMember() - { - // Arrange & Act - DeleteRestrictions delete = new DeleteRestrictions(); - - // Assert - Assert.Equal(CapabilitesTermKind.DeleteRestrictions, delete.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultDeleteRestrictionsValues() - { - // Arrange - DeleteRestrictions delete = new DeleteRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = delete.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(delete.IsDeletable); - Assert.Null(delete.Deletable); - Assert.Null(delete.NonDeletableNavigationProperties); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectDeleteRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - DeleteRestrictions delete = new DeleteRestrictions(); - bool result = delete.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyDeleteRestrictions(delete); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectDeleteRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - DeleteRestrictions delete = new DeleteRestrictions(); - bool result = delete.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyDeleteRestrictions(delete); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @" - - - - - - abc - RelatedEvents - - - - "; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - - private static void VerifyDeleteRestrictions(DeleteRestrictions delete) - { - Assert.NotNull(delete); - - Assert.NotNull(delete.Deletable); - Assert.False(delete.Deletable.Value); - - Assert.NotNull(delete.NonDeletableNavigationProperties); - Assert.Equal(2, delete.NonDeletableNavigationProperties.Count); - Assert.Equal("abc|RelatedEvents", String.Join("|", delete.NonDeletableNavigationProperties)); - - Assert.True(delete.IsNonDeletableNavigationProperty("RelatedEvents")); - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/IndexableByKeyTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/IndexableByKeyTests.cs deleted file mode 100644 index b32184a..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/IndexableByKeyTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -// ------------------------------------------------------------ -// 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.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class IndexableByKeyTests - { - [Fact] - public void KindPropertyReturnsIndexableByKeyEnumMember() - { - // Arrange & Act - IndexableByKey index = new IndexableByKey(); - - // Assert - Assert.Equal(CapabilitesTermKind.IndexableByKey, index.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultIndexableByKeyValues() - { - // Arrange - IndexableByKey index = new IndexableByKey(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = index.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(index.IsSupported); - Assert.Null(index.Supported); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectIndexableByKeyValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - IndexableByKey index = new IndexableByKey(); - bool result = index.Load(model, calendars); - - // Assert - Assert.True(result); - Assert.NotNull(index.Supported); - Assert.False(index.Supported.Value); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectIndexableByKeyValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - IndexableByKey index = new IndexableByKey(); - bool result = index.Load(model, calendars); - - // Assert - Assert.True(result); - Assert.NotNull(index.Supported); - Assert.False(index.Supported.Value); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @""; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/InsertRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/InsertRestrictionsTests.cs deleted file mode 100644 index 6f619fe..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/InsertRestrictionsTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -// ------------------------------------------------------------ -// 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 Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class InsertRestrictionsTests - { - [Fact] - public void KindPropertyReturnsInsertRestrictionsEnumMember() - { - // Arrange & Act - InsertRestrictions insert = new InsertRestrictions(); - - // Assert - Assert.Equal(CapabilitesTermKind.InsertRestrictions, insert.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultInsertRestrictionsValues() - { - // Arrange - InsertRestrictions insert = new InsertRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = insert.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(insert.IsInsertable); - Assert.Null(insert.Insertable); - Assert.Null(insert.NonInsertableNavigationProperties); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectInsertRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - InsertRestrictions insert = new InsertRestrictions(); - bool result = insert.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyInsertRestrictions(insert); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectInsertRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - InsertRestrictions insert = new InsertRestrictions(); - bool result = insert.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyInsertRestrictions(insert); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @" - - - - - - abc - RelatedEvents - - - - "; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - - private static void VerifyInsertRestrictions(InsertRestrictions insert) - { - Assert.NotNull(insert); - - Assert.NotNull(insert.Insertable); - Assert.False(insert.Insertable.Value); - - Assert.NotNull(insert.NonInsertableNavigationProperties); - Assert.Equal(2, insert.NonInsertableNavigationProperties.Count); - Assert.Equal("abc|RelatedEvents", String.Join("|", insert.NonInsertableNavigationProperties)); - - Assert.True(insert.IsNonInsertableNavigationProperty("RelatedEvents")); - Assert.False(insert.IsNonInsertableNavigationProperty("MyUnknownNavigationProperty")); - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SkipSupportedTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SkipSupportedTests.cs deleted file mode 100644 index c1c307e..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SkipSupportedTests.cs +++ /dev/null @@ -1,112 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class SkipSupportedTests - { - [Fact] - public void KindPropertyReturnsSkipSupportedEnumMember() - { - // Arrange & Act - SkipSupported skip = new SkipSupported(); - - // Assert - Assert.Equal(CapabilitesTermKind.SkipSupported, skip.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultSkipSupportedValues() - { - // Arrange - SkipSupported skip = new SkipSupported(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = skip.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(skip.IsSupported); - Assert.Null(skip.Supported); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectSkipSupportedValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); - Assert.NotNull(calendar); // guard - - // Act - SkipSupported skip = new SkipSupported(); - bool result = skip.Load(model, calendar); - - // Assert - Assert.True(result); - Assert.False(skip.IsSupported); - Assert.NotNull(skip.Supported); - Assert.False(skip.Supported.Value); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectSkipSupportedValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - SkipSupported skip = new SkipSupported(); - bool result = skip.Load(model, calendars); - - // Assert - Assert.True(result); - Assert.NotNull(skip.Supported); - Assert.False(skip.Supported.Value); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @""; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/TopSupportedTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/TopSupportedTests.cs deleted file mode 100644 index bc74969..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/TopSupportedTests.cs +++ /dev/null @@ -1,113 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. -// ------------------------------------------------------------ - -using System.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class TopSupportedTests - { - [Fact] - public void KindPropertyReturnsTopSupportedEnumMember() - { - // Arrange & Act - TopSupported top = new TopSupported(); - - // Assert - Assert.Equal(CapabilitesTermKind.TopSupported, top.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultTopSupportedValues() - { - // Arrange - TopSupported top = new TopSupported(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = top.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(top.IsSupported); - Assert.Null(top.Supported); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectTopSupportedValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); - Assert.NotNull(calendar); // guard - - // Act - TopSupported top = new TopSupported(); - bool result = top.Load(model, calendar); - - // Assert - Assert.True(result); - Assert.False(top.IsSupported); - Assert.NotNull(top.Supported); - Assert.False(top.Supported.Value); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectTopSupportedValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - TopSupported top = new TopSupported(); - bool result = top.Load(model, calendars); - - // Assert - Assert.True(result); - Assert.False(top.IsSupported); - Assert.NotNull(top.Supported); - Assert.False(top.Supported.Value); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string topAnnotation = @""; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - topAnnotation = string.Format(template, topAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(topAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(topAnnotation); - } - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/UpdateRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/UpdateRestrictionsTests.cs deleted file mode 100644 index 75fe73e..0000000 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/UpdateRestrictionsTests.cs +++ /dev/null @@ -1,138 +0,0 @@ -// ------------------------------------------------------------ -// 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 Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; -using Xunit; - -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests -{ - public class UpdateRestrictionsTests - { - [Fact] - public void KindPropertyReturnsUpdateRestrictionsEnumMember() - { - // Arrange & Act - UpdateRestrictions update = new UpdateRestrictions(); - - // Assert - Assert.Equal(CapabilitesTermKind.UpdateRestrictions, update.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultUpdateRestrictionsValues() - { - // Arrange - UpdateRestrictions update = new UpdateRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = update.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(update.IsUpdatable); - Assert.Null(update.Updatable); - Assert.Null(update.NonUpdatableNavigationProperties); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectUpdateRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); - Assert.NotNull(calendar); // guard - - // Act - UpdateRestrictions update = new UpdateRestrictions(); - bool result = update.Load(model, calendar); - - // Assert - Assert.True(result); - VerifyUpdateRestrictions(update); - } - - [Theory] - [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] - [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntitySetReturnsCorrectUpdateRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) - { - // Arrange - const string template = @" - - {0} - "; - - IEdmModel model = GetEdmModel(template, location); - Assert.NotNull(model); // guard - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - Assert.NotNull(calendars); // guard - - // Act - UpdateRestrictions update = new UpdateRestrictions(); - bool result = update.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyUpdateRestrictions(update); - } - - private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) - { - string countAnnotation = @" - - - - - - abc - RelatedEvents - - - - "; - - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - countAnnotation = string.Format(template, countAnnotation); - return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); - } - else - { - return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); - } - } - - private static void VerifyUpdateRestrictions(UpdateRestrictions update) - { - Assert.NotNull(update); - - Assert.NotNull(update.Updatable); - Assert.False(update.Updatable.Value); - - Assert.NotNull(update.NonUpdatableNavigationProperties); - Assert.Equal(2, update.NonUpdatableNavigationProperties.Count); - Assert.Equal("abc|RelatedEvents", String.Join("|", update.NonUpdatableNavigationProperties)); - - Assert.True(update.IsNonUpdatableNavigationProperty("abc")); - Assert.True(update.IsNonUpdatableNavigationProperty("RelatedEvents")); - Assert.False(update.IsNonUpdatableNavigationProperty("Others")); - } - } -} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs index 6f70c96..7b13bd8 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Common/EdmModelHelper.cs @@ -355,7 +355,7 @@ namespace Microsoft.OpenApi.OData.Tests Assert.Equal(expected, actual); } - private string GetCsdl(IEdmModel model) + public static string GetCsdl(IEdmModel model) { string edmx = string.Empty; diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/EdmVocabularyAnnotationExtensionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/EdmVocabularyAnnotationExtensionsTests.cs new file mode 100644 index 0000000..7d44b7b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Edm/EdmVocabularyAnnotationExtensionsTests.cs @@ -0,0 +1,253 @@ +// ------------------------------------------------------------ +// 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 System.Runtime.InteropServices; +using System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Validation; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Edm.Tests +{ + public class EdmVocabularyAnnotationExtensionsTests + { + [Fact] + public void GetStringWorksForString() + { + // Arrange + string qualifiedName = "Org.OData.Core.V1.ODataVersions"; + string annotation = $@""; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + string versions1 = model.GetString(model.EntityContainer, qualifiedName); + string versions2 = model.GetString(model.EntityContainer, qualifiedName); + + // Assert + Assert.NotNull(versions1); + Assert.NotNull(versions2); + Assert.Same(versions1, versions2); + Assert.Equal("9.99,4.01", versions1); + Assert.Equal("9.99,4.01", versions2); + } + + [Fact] + public void GetStringWorksForMutlipleModels() + { + // Arrange + string qualifiedName = "Org.OData.Core.V1.ODataVersions"; + string annotation = $@""; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + IEdmModel coreModel = EdmCoreModel.Instance; + + // Act & Assert + string versions1 = model.GetString(model.EntityContainer, qualifiedName); + Assert.NotNull(versions1); + + string versions2 = coreModel.GetString(model.EntityContainer, qualifiedName); + Assert.Null(versions2); + + string versions3 = model.GetString(model.EntityContainer, qualifiedName); + Assert.NotNull(versions3); + + Assert.Equal(versions1, versions3); + } + + [Fact] + public void GetRecordWorksForRecord() + { + // Arrange + string qualifiedName = "Org.OData.Capabilities.V1.CountRestrictions"; + string annotation = $@" + + + + + + Emails + mij + + + + + RelatedEvents + abc + + + +"; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + CountRestrictionsType count1 = model.GetRecord(model.EntityContainer, qualifiedName); + CountRestrictionsType count2 = model.GetRecord(model.EntityContainer, qualifiedName); + + // Assert + Assert.NotNull(count1); + Assert.NotNull(count2); + Assert.Same(count1, count2); + + // Countable + Assert.NotNull(count1.Countable); + Assert.True(count1.Countable.Value); + + // NonCountableProperties + Assert.NotNull(count1.NonCountableProperties); + Assert.Equal(new[] { "Emails", "mij" }, count1.NonCountableProperties); + + // NonCountableNavigationProperties + Assert.NotNull(count1.NonCountableNavigationProperties); + Assert.Equal(new[] { "RelatedEvents", "abc" }, count1.NonCountableNavigationProperties); + } + + [Fact] + public void GetCollectionWorksForCollectionOfString() + { + // Arrange + string qualifiedName = "Org.OData.Capabilities.V1.SupportedFormats"; + string annotation = $@" + + + abc + xyz + +"; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + IEnumerable supportedFormats1 = model.GetCollection(model.EntityContainer, qualifiedName); + IEnumerable supportedFormats2 = model.GetCollection(model.EntityContainer, qualifiedName); + + // Assert + Assert.NotNull(supportedFormats1); + Assert.NotNull(supportedFormats2); + Assert.Same(supportedFormats1, supportedFormats2); + + Assert.Equal(2, supportedFormats1.Count()); + Assert.Equal(new[] { "abc", "xyz" }, supportedFormats1); + } + + [Fact] + public void GetGenericCollectionWorksForCollectionOfGenericRecord() + { + // Arrange + string qualifiedName = "NS.MyCollectionCountRestrictions"; + string annotation = $@" + + + + + + + 123 + abc + + + + + 234 + xyz + + + + + + + + 567 + mij + + + + + 789 + rst + + + + +"; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + IEnumerable counts1 = model.GetCollection(model.EntityContainer, qualifiedName); + IEnumerable counts2 = model.GetCollection(model.EntityContainer, qualifiedName); + + // Assert + Assert.NotNull(counts1); + Assert.NotNull(counts2); + + Assert.Equal(2, counts1.Count()); + + foreach (var countItem in new[] { counts1, counts2 }) + { + CountRestrictionsType count = countItem.First(); + + // Countable + Assert.NotNull(count.Countable); + Assert.True(count.Countable.Value); + + // NonCountableProperties + Assert.NotNull(count.NonCountableProperties); + Assert.Equal(new[] { "123", "abc" }, count.NonCountableProperties); + + // NonCountableNavigationProperties + Assert.NotNull(count.NonCountableNavigationProperties); + Assert.Equal(new[] { "234", "xyz" }, count.NonCountableNavigationProperties); + + // #2 + count = countItem.Last(); + + // Countable + Assert.NotNull(count.Countable); + Assert.False(count.Countable.Value); + + // NonCountableProperties + Assert.NotNull(count.NonCountableProperties); + Assert.Equal(new[] { "567", "mij" }, count.NonCountableProperties); + + // NonCountableNavigationProperties + Assert.NotNull(count.NonCountableNavigationProperties); + Assert.Equal(new[] { "789", "rst" }, count.NonCountableNavigationProperties); + } + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + IEnumerable errors; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out errors); + Assert.True(result); + return model; + } + } +} 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 bea7149..301d4c1 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,8 +62,11 @@ - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs index 7d25cc0..101e4b4 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmActionOperationHandlerTests.cs @@ -132,7 +132,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests if (enableOperationId) { - Assert.Equal("Customers.VipCustomer.MyAction", operation.OperationId); + Assert.Equal("Customers.NS.VipCustomer.MyAction", operation.OperationId); } else { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs index 03f81b0..da8243a 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/EdmFunctionOperationHandlerTests.cs @@ -136,7 +136,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests if (enableOperationId) { - Assert.Equal("Customers.VipCustomer.MyFunction.1e00", operation.OperationId); + Assert.Equal("Customers.NS.VipCustomer.MyFunction.1e00", operation.OperationId); } else { diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs index 81a344b..d290340 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonGetOperationHandlerTests.cs @@ -68,7 +68,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests [InlineData(false, false)] [InlineData(true, true)] [InlineData(true, false)] - public void CreateSingletonSetGetOperationReturnsParameterForExpandRestrictions(bool hasRestriction, bool expandable) + public void CreateSingletonGetOperationReturnsParameterForExpandRestrictions(bool hasRestriction, bool expandable) { // Arrange string annotation = String.Format(@" diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs index 5e4363e..230fb62 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Operation/SingletonPatchOperationHandlerTests.cs @@ -5,7 +5,9 @@ using System.Linq; using Microsoft.OData.Edm; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests; using Xunit; namespace Microsoft.OpenApi.OData.Operation.Tests @@ -55,5 +57,162 @@ namespace Microsoft.OpenApi.OData.Operation.Tests Assert.Null(patch.OperationId); } } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CreateSingletonPatchOperationReturnsParameterForUpdateRestrictions(bool hasRestriction) + { + // Arrange + string annotation = @" + + + + + + abc + RelatedEvents + + + + + + + + + + + RequiredScopes1 + RequiredScopes2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + // Act & Assert + VerifyOperation(annotation, hasRestriction); + } + + private void VerifyOperation(string annotation, bool hasRestriction) + { + // Arrange + IEdmModel model = CapabilitiesModelHelper.GetEdmModelOutline(hasRestriction ? annotation : ""); + ODataContext context = new ODataContext(model); + IEdmSingleton me = model.EntityContainer.FindSingleton("Me"); + Assert.NotNull(me); // guard + ODataPath path = new ODataPath(new ODataNavigationSourceSegment(me)); + + // Act + var patch = _operationHandler.CreateOperation(context, path); + + // Assert + Assert.NotNull(patch); + + Assert.NotNull(patch.Parameters); + if (hasRestriction) + { + // Parameters + Assert.Equal(3, patch.Parameters.Count); + + Assert.Equal(ParameterLocation.Header, patch.Parameters[0].In); + Assert.Equal("HeadName1", patch.Parameters[0].Name); + + Assert.Equal(ParameterLocation.Header, patch.Parameters[1].In); + Assert.Equal("HeadName2", patch.Parameters[1].Name); + + Assert.Equal(ParameterLocation.Query, patch.Parameters[2].In); + Assert.Equal("QueryName1", patch.Parameters[2].Name); + + // security + Assert.NotNull(patch.Security); + var securityRequirements = Assert.Single(patch.Security); + var securityRequirement = Assert.Single(securityRequirements); + Assert.Equal("authorizationName", securityRequirement.Key.Reference.Id); + Assert.Equal(new[] { "scopeName1", "scopeName2" }, securityRequirement.Value); + } + else + { + Assert.Empty(patch.Parameters); + Assert.Empty(patch.Security); + } + } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs index 17c41c7..9534afc 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntityPathItemHandlerTests.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests { public class EntityPathItemHandlerTests { - private EntityPathItemHandler _pathItemHandler = new EntityPathItemHandler(); + private EntityPathItemHandler _pathItemHandler = new MyEntityPathItemHandler(); [Fact] public void CreatePathItemThrowsForNullContext() @@ -49,7 +49,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests // Assert var exception = Assert.Throws(test); - Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, "EntityPathItemHandler", path.Kind), exception.Message); + Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, _pathItemHandler.GetType().Name, path.Kind), exception.Message); } [Fact] @@ -78,27 +78,39 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests [Theory] [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })] [InlineData(false, new OperationType[] { OperationType.Patch, OperationType.Delete })] - public void CreateEntityPathItemWorksForIndexableByKeyRestrictionsCapablities(bool indexableByKey, OperationType[] expected) + public void CreateEntityPathItemWorksForReadByKeyRestrictionsCapablities(bool readable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" -", indexableByKey); - - IEdmModel model = EntitySetPathItemHandlerTests.GetEdmModel(annotation); - ODataContext context = new ODataContext(model); - IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); - Assert.NotNull(entitySet); // guard - ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType())); - - // Act - var pathItem = _pathItemHandler.CreatePathItem(context, path); + string annotation = $@" + + + + + + + + +"; // Assert - Assert.NotNull(pathItem); + VerifyPathItemOperations(annotation, expected); + } - Assert.NotNull(pathItem.Operations); - Assert.NotEmpty(pathItem.Operations); - Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); + [Theory] + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })] + [InlineData(false, new OperationType[] { OperationType.Patch, OperationType.Delete })] + public void CreateEntityPathItemWorksForReadRestrictionsCapablities(bool readable, OperationType[] expected) + { + // Arrange + string annotation = $@" + + + + +"; + + // Assert + VerifyPathItemOperations(annotation, expected); } [Theory] @@ -107,28 +119,15 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests public void CreateEntityPathItemWorksForUpdateRestrictionsCapablities(bool updatable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" + string annotation = $@" - + -", updatable); - - IEdmModel model = EntitySetPathItemHandlerTests.GetEdmModel(annotation); - ODataContext context = new ODataContext(model); - IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); - Assert.NotNull(entitySet); // guard - ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType())); - - // 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)); + VerifyPathItemOperations(annotation, expected); } [Theory] @@ -137,13 +136,20 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests public void CreateEntityPathItemWorksForDeleteRestrictionsCapablities(bool deletable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" + string annotation = $@" - + -", deletable); +"; + // Assert + VerifyPathItemOperations(annotation, expected); + } + + private void VerifyPathItemOperations(string annotation, OperationType[] expected) + { + // Arrange IEdmModel model = EntitySetPathItemHandlerTests.GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); @@ -161,4 +167,12 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); } } + + internal class MyEntityPathItemHandler : EntityPathItemHandler + { + protected override void AddOperation(OpenApiPathItem item, OperationType operationType) + { + item.AddOperation(operationType, new OpenApiOperation()); + } + } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntitySetPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntitySetPathItemHandlerTests.cs index 76f2c93..e3ca808 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntitySetPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/EntitySetPathItemHandlerTests.cs @@ -19,7 +19,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests { public class EntitySetPathItemHandlerTests { - private EntitySetPathItemHandler _pathItemHandler = new EntitySetPathItemHandler(); + private EntitySetPathItemHandler _pathItemHandler = new MyEntitySetPathItemHandler(); [Fact] public void CreatePathItemThrowsForNullContext() @@ -53,7 +53,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests // Assert var exception = Assert.Throws(test); - Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, "EntitySetPathItemHandler", path.Kind), exception.Message); + Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, _pathItemHandler.GetType().Name, path.Kind), exception.Message); } [Fact] @@ -80,45 +80,20 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests } [Theory] - [InlineData("None")] - [InlineData("Single")] - [InlineData("Recursive")] - public void CreateEntitySetPathItemWorksForNavigationRestrictionsCapablities(string navigationType) + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Post })] + [InlineData(false, new OperationType[] { OperationType.Post })] + public void CreateEntitySetPathItemWorksForReadRestrictionsCapablities(bool readable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" - + string annotation = $@" + - - Org.OData.Capabilities.V1.NavigationType/{0} - + -", navigationType); - - IEdmModel model = GetEdmModel(annotation); - ODataContext context = new ODataContext(model); - IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); - Assert.NotNull(entitySet); // guard - ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet)); - - // Act - var pathItem = _pathItemHandler.CreatePathItem(context, path); +"; // Assert - Assert.NotNull(pathItem); - - Assert.NotNull(pathItem.Operations); - Assert.NotEmpty(pathItem.Operations); - Assert.Contains(OperationType.Post, pathItem.Operations.Select(e => e.Key)); - - if (navigationType == "None") - { - Assert.DoesNotContain(OperationType.Get, pathItem.Operations.Select(e => e.Key)); - } - else - { - Assert.Contains(OperationType.Get, pathItem.Operations.Select(e => e.Key)); - } + VerifyPathItemOperations(annotation, expected); } [Theory] @@ -127,13 +102,40 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests public void CreateEntitySetPathItemWorksForInsertRestrictionsCapablities(bool insertable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" + string annotation = $@" - + -", insertable); +"; + // Assert + VerifyPathItemOperations(annotation, expected); + } + + [Fact] + public void CreateEntitySetPathItemWorksForReadAndInsertRestrictionsCapablities() + { + // Arrange + string annotation = @" + + + + + + + + + +"; + + // Assert + VerifyPathItemOperations(annotation, new OperationType[] { }); + } + + private void VerifyPathItemOperations(string annotation, OperationType[] expected) + { + // Arrange IEdmModel model = GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); @@ -147,7 +149,6 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests Assert.NotNull(pathItem); Assert.NotNull(pathItem.Operations); - Assert.NotEmpty(pathItem.Operations); Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); } @@ -181,4 +182,12 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests return model; } } + + internal class MyEntitySetPathItemHandler : EntitySetPathItemHandler + { + protected override void AddOperation(OpenApiPathItem item, OperationType operationType) + { + item.AddOperation(operationType, new OpenApiOperation()); + } + } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/OperationImportPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/OperationImportPathItemHandlerTests.cs index a6a22d1..a6254a4 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/OperationImportPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/OperationImportPathItemHandlerTests.cs @@ -5,7 +5,9 @@ using System; using System.Linq; +using System.Xml.Linq; using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.OData.Edm; using Microsoft.OpenApi.OData.Properties; @@ -16,7 +18,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests { public class OperationImportPathItemHandlerTest { - private OperationImportPathItemHandler _pathItemHandler = new OperationImportPathItemHandler(); + private OperationImportPathItemHandler _pathItemHandler = new MyOperationImportPathItemHandler(); [Fact] public void CreatePathItemThrowsForNullContext() @@ -50,7 +52,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests // Assert var exception = Assert.Throws(test); - Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, "OperationImportPathItemHandler", path.Kind), exception.Message); + Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, _pathItemHandler.GetType().Name, path.Kind), exception.Message); } [Theory] @@ -65,8 +67,6 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests IEdmOperationImport edmOperationImport = model.EntityContainer .OperationImports().FirstOrDefault(o => o.Name == operationImport); Assert.NotNull(edmOperationImport); // guard - string expectSummary = "Invoke " + - (edmOperationImport.IsActionImport() ? "actionImport " : "functionImport ") + operationImport; ODataPath path = new ODataPath(new ODataOperationImportSegment(edmOperationImport)); // Act @@ -78,8 +78,91 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests var operationKeyValue = Assert.Single(pathItem.Operations); Assert.Equal(operationType, operationKeyValue.Key); Assert.NotNull(operationKeyValue.Value); + } - Assert.Equal(expectSummary, operationKeyValue.Value.Summary); + [Theory] + [InlineData(true, "GetNearestCustomers", OperationType.Get)] + [InlineData(false, "GetNearestCustomers", null)] + [InlineData(true, "ResetDataSource", OperationType.Post)] + [InlineData(false, "ResetDataSource", OperationType.Post)] + public void CreatePathItemForOperationImportWithReadRestrictionsReturnsCorrectPathItem(bool readable, string operationImport, + OperationType? operationType) + { + // Arrange + string annotation = $@" + + + + +"; + + IEdmModel model = GetEdmModel(annotation); + ODataContext context = new ODataContext(model); + IEdmOperationImport edmOperationImport = model.EntityContainer + .OperationImports().FirstOrDefault(o => o.Name == operationImport); + Assert.NotNull(edmOperationImport); // guard + ODataPath path = new ODataPath(new ODataOperationImportSegment(edmOperationImport)); + + // Act + OpenApiPathItem pathItem = _pathItemHandler.CreatePathItem(context, path); + + // Assert + Assert.NotNull(pathItem); + Assert.NotNull(pathItem.Operations); + if (operationType == null) + { + Assert.Empty(pathItem.Operations); + } + else + { + var operationKeyValue = Assert.Single(pathItem.Operations); + Assert.Equal(operationType, operationKeyValue.Key); + Assert.NotNull(operationKeyValue.Value); + } + } + + public static IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + + + + + + + + + + + + + + {0} + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } + + internal class MyOperationImportPathItemHandler : OperationImportPathItemHandler + { + protected override void AddOperation(OpenApiPathItem item, OperationType operationType) + { + item.AddOperation(operationType, new OpenApiOperation()); } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/SingletonPathItemHandlerTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/SingletonPathItemHandlerTests.cs index 0e71c7d..b00aa16 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/SingletonPathItemHandlerTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/PathItem/SingletonPathItemHandlerTests.cs @@ -20,7 +20,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests { public class SingletonPathItemHandlerTest { - private SingletonPathItemHandler _pathItemHandler = new SingletonPathItemHandler(); + private SingletonPathItemHandler _pathItemHandler = new MySingletonPathItemHandler(); [Fact] public void CreatePathItemThrowsForNullContext() @@ -53,7 +53,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests // Assert var exception = Assert.Throws(test); - Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, "SingletonPathItemHandler", path.Kind), exception.Message); + Assert.Equal(String.Format(SRResource.InvalidPathKindForPathItemHandler, _pathItemHandler.GetType().Name, path.Kind), exception.Message); } [Fact] @@ -80,57 +80,42 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests } [Theory] - [InlineData("None")] - [InlineData("Single")] - [InlineData("Recursive")] - public void CreateSingletonPathItemWorksForNavigationRestrictionsCapablities(string navigationType) + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch })] + [InlineData(false, new OperationType[] { OperationType.Patch })] + public void CreateSingletonPathItemWorksForReadRestrictionsCapablities(bool readable, OperationType[] expected) { // Arrange - string annotation = String.Format(@" - + string annotation = $@" + - - Org.OData.Capabilities.V1.NavigationType/{0} - - -", navigationType); - IEdmModel model = GetEdmModel(annotation); - ODataContext context = new ODataContext(model); - IEdmSingleton singleton = model.EntityContainer.FindSingleton("Me"); - Assert.NotNull(singleton); // guard - ODataPath path = new ODataPath(new ODataNavigationSourceSegment(singleton)); - - // Act - var pathItem = _pathItemHandler.CreatePathItem(context, path); - - // Assert - Assert.NotNull(pathItem); - - Assert.NotNull(pathItem.Operations); - Assert.NotEmpty(pathItem.Operations); - if (navigationType == "None") - { - var operation = Assert.Single(pathItem.Operations); - Assert.Equal(OperationType.Patch, operation.Key); - } - else - { - Assert.Equal(2, pathItem.Operations.Count); - Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Patch }, - pathItem.Operations.Select(o => o.Key)); - } - } - - [Fact] - public void CreateSingletonPathItemWorksForUpdateRestrictionsCapablities() - { - // Arrange - string annotation = @" - - - + "; + + // Assert + VerifyPathItemOperations(annotation, expected); + } + + [Theory] + [InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch })] + [InlineData(false, new OperationType[] { OperationType.Get })] + public void CreateSingletonPathItemWorksForUpdateRestrictionsCapablities(bool updatable, OperationType[] expected) + { + // Arrange + string annotation = $@" + + + + +"; + + // Assert + VerifyPathItemOperations(annotation, expected); + } + + private void VerifyPathItemOperations(string annotation, OperationType[] expected) + { + // Arrange IEdmModel model = GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmSingleton singleton = model.EntityContainer.FindSingleton("Me"); @@ -145,8 +130,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests Assert.NotNull(pathItem.Operations); Assert.NotEmpty(pathItem.Operations); - var operation = Assert.Single(pathItem.Operations); - Assert.Equal(OperationType.Get, operation.Key); + Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); } private IEdmModel GetEdmModel(string annotation) @@ -179,4 +163,12 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests return model; } } + + internal class MySingletonPathItemHandler : SingletonPathItemHandler + { + protected override void AddOperation(OpenApiPathItem item, OperationType operationType) + { + item.AddOperation(operationType, new OpenApiOperation()); + } + } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/ApiKeyTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/ApiKeyTests.cs new file mode 100644 index 0000000..e4e1c9c --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/ApiKeyTests.cs @@ -0,0 +1,119 @@ +// ------------------------------------------------------------ +// 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 System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class ApiKeyTests + { + [Fact] + public void SchemeTypeKindSetCorrectly() + { + // Arrange + ApiKey apiKey = new ApiKey(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.ApiKey, apiKey.SchemeType); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new ApiKey().Initialize(record: null)); + } + + [Fact] + public void InitializeApiKeyWithRecordSuccess() + { + // Arrange + EdmModel model = new EdmModel(); + IEdmType edmType = model.FindType("Org.OData.Authorization.V1.KeyLocation"); + IEdmEnumType enumType = edmType as IEdmEnumType; + IEdmEnumMember enumMember = enumType.Members.FirstOrDefault(c => c.Name == "Header"); + Assert.NotNull(enumMember); + + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("DelegatedWork")), + new EdmPropertyConstructor("Description", new EdmStringConstant("Description of the authorization scheme")), + new EdmPropertyConstructor("KeyName", new EdmStringConstant("keyName")), + new EdmPropertyConstructor("Location", new EdmEnumMemberExpression(enumMember))); + + ApiKey apiKey = new ApiKey(); + Assert.Null(apiKey.Name); + Assert.Null(apiKey.Description); + Assert.Null(apiKey.Location); + Assert.Null(apiKey.KeyName); + + // Act + apiKey.Initialize(record); + + // Assert + Assert.Equal("DelegatedWork", apiKey.Name); + Assert.Equal("Description of the authorization scheme", apiKey.Description); + Assert.Equal("keyName", apiKey.KeyName); + Assert.Equal(KeyLocation.Header, apiKey.Location); + } + + [Fact] + public void InitializeApiKeyWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + ApiKey apiKey = model.GetRecord(model.EntityContainer, "NS.MyApiKey"); + + // Assert + Assert.NotNull(apiKey); + Assert.Equal("DelegatedWork", apiKey.Name); + Assert.Equal("Description of the authorization scheme", apiKey.Description); + Assert.Equal("keyName", apiKey.KeyName); + Assert.Equal(KeyLocation.QueryOption, apiKey.Location); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationScopeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationScopeTests.cs new file mode 100644 index 0000000..e9fceec --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationScopeTests.cs @@ -0,0 +1,94 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class AuthorizationScopeTests + { + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new AuthorizationScope().Initialize(record: null)); + } + + [Fact] + public void InitializeAuthorizationScopeWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Scope", new EdmStringConstant("ScopeName")), + new EdmPropertyConstructor("Grant", new EdmStringConstant("GrantAccess"))); + + AuthorizationScope scope = new AuthorizationScope(); + Assert.Null(scope.Scope); + Assert.Null(scope.Description); + Assert.Null(scope.Grant); + + // Act + scope.Initialize(record); + + // Assert + Assert.Equal("ScopeName", scope.Scope); + Assert.Null(scope.Description); + Assert.Equal("GrantAccess", scope.Grant); + } + + [Fact] + public void InitializeAuthorizationScopeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + AuthorizationScope scope = model.GetRecord(model.EntityContainer, "NS.MyAuthorizationScope"); + + // Assert + Assert.NotNull(scope); + Assert.Equal("Scope name", scope.Scope); + Assert.Equal("Description of the scope", scope.Description); + Assert.Equal("grant access", scope.Grant); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationTests.cs new file mode 100644 index 0000000..22a103b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationTests.cs @@ -0,0 +1,79 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Exceptions; +using Microsoft.OpenApi.OData.Properties; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class AuthorizationTests + { + [Fact] + public void CreateAuthorizationReturnsNullWithNullRecord() + { + // Arrange & Act + var authorization = OData.Vocabulary.Authorization.Authorization.CreateAuthorization(record: null); + + // Assert + Assert.Null(authorization); + } + + [Fact] + public void CreateAuthorizationThrowsForOAuthAuthorizationRecord() + { + // Arrange & Act + IEdmStructuredTypeReference structuredTypeRef = GetType("Org.OData.Authorization.V1.OAuthAuthorization"); + IEdmRecordExpression record = new EdmRecordExpression(structuredTypeRef, + new EdmPropertyConstructor("Name", new EdmStringConstant("temp"))); + + Action test = () => OData.Vocabulary.Authorization.Authorization.CreateAuthorization(record); + + // Assert + OpenApiException exception = Assert.Throws(test); + Assert.Equal(String.Format(SRResource.AuthorizationRecordTypeNameNotCorrect, structuredTypeRef.FullName()), exception.Message); + } + + [Theory] + [InlineData(typeof(OpenIDConnect))] + [InlineData(typeof(Http))] + [InlineData(typeof(ApiKey))] + [InlineData(typeof(OAuth2ClientCredentials))] + [InlineData(typeof(OAuth2Implicit))] + [InlineData(typeof(OAuth2Password))] + [InlineData(typeof(OAuth2AuthCode))] + public void CreateAuthorizationReturnsOpenIDConnect(Type type) + { + // Arrange & Act + string qualifiedName = AuthorizationConstants.Namespace + "." + type.Name; + IEdmRecordExpression record = new EdmRecordExpression(GetType(qualifiedName), + new EdmPropertyConstructor("Name", new EdmStringConstant("temp"))); + + // Assert + var authorization = OData.Vocabulary.Authorization.Authorization.CreateAuthorization(record); + Assert.NotNull(authorization); + Assert.Equal(type, authorization.GetType()); + + Assert.Equal("temp", authorization.Name); + Assert.Null(authorization.Description); + } + + private static IEdmStructuredTypeReference GetType(string qualifiedName) + { + EdmModel model = new EdmModel(); + IEdmType edmType = model.FindType(qualifiedName); + Assert.NotNull(edmType); + + IEdmComplexType complexType = edmType as IEdmComplexType; + Assert.NotNull(complexType); + + return new EdmComplexTypeReference(complexType, true); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationVocabularyTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationVocabularyTests.cs new file mode 100644 index 0000000..848a466 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/AuthorizationVocabularyTests.cs @@ -0,0 +1,90 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.IO; +using System.Linq; +using System.Xml; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class AuthorizationVocabularyTests + { + [Fact] + public void GetAuthorizationsReturnsNullForTargetWithoutAuthorization() + { + // Arrange + EdmModel model = new EdmModel(); + EdmEntityContainer container = new EdmEntityContainer("NS", "Container"); + model.AddElement(container); + + // Act + var authorizations = model.GetAuthorizations(container); + + // Assert + Assert.Null(authorizations); + } + + [Fact] + public void GetAuthorizationsReturnsForEdmModelNavigationSourceWithAuthroizations() + { + // Arrange + IEdmModel model = GetEdmModel(); + Assert.NotNull(model.EntityContainer); + + // Act + var authorizations = model.GetAuthorizations(model.EntityContainer); + + // Assert + Assert.NotEmpty(authorizations); + Assert.Equal(2, authorizations.Count()); + + // #1 + OpenIDConnect openID = Assert.IsType(authorizations.First()); + Assert.Equal("OpenIDConnect Name", openID.Name); + Assert.Equal("http://any", openID.IssuerUrl); + Assert.Equal("OpenIDConnect Description", openID.Description); + + // #2 + Http http = Assert.IsType(authorizations.Last()); + Assert.Equal("Http Name", http.Name); + Assert.Equal("Http Scheme", http.Scheme); + Assert.Equal("Http BearerFormat", http.BearerFormat); + Assert.Null(http.Description); + } + + private static IEdmModel GetEdmModel() + { + const string schema = @" + + + + + + + + + + + + + + + + + +"; + + IEdmModel parsedModel; + bool parsed = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out parsedModel, out _); + Assert.True(parsed); + return parsedModel; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/HttpTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/HttpTests.cs new file mode 100644 index 0000000..f775dc5 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/HttpTests.cs @@ -0,0 +1,111 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class HttpTests + { + [Fact] + public void SchemeTypeKindSetCorrectly() + { + // Arrange + Http http = new Http(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.Http, http.SchemeType); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new Http().Initialize(record: null)); + } + + [Fact] + public void InitializeHttpWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("HttpWork")), + new EdmPropertyConstructor("Description", new EdmStringConstant("Description of the scheme")), + new EdmPropertyConstructor("Scheme", new EdmStringConstant("Authorization scheme")), + new EdmPropertyConstructor("BearerFormat", new EdmStringConstant("Format of the bearer token"))); + + Http http = new Http(); + Assert.Null(http.Name); + Assert.Null(http.Description); + Assert.Null(http.Scheme); + Assert.Null(http.BearerFormat); + + // Act + http.Initialize(record); + + // Assert + Assert.Equal("HttpWork", http.Name); + Assert.Equal("Description of the scheme", http.Description); + Assert.Equal("Authorization scheme", http.Scheme); + Assert.Equal("Format of the bearer token", http.BearerFormat); + } + + [Fact] + public void InitializeHttpWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + Http http = model.GetRecord(model.EntityContainer, "NS.MyHttp"); + + // Assert + Assert.NotNull(http); + Assert.Equal("HttpWork", http.Name); + Assert.Null(http.Description); + Assert.Equal("Authorization scheme", http.Scheme); + Assert.Equal("Format of the bearer token", http.BearerFormat); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2AuthCodeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2AuthCodeTests.cs new file mode 100644 index 0000000..420098b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2AuthCodeTests.cs @@ -0,0 +1,110 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class OAuth2AuthCodeTests + { + [Fact] + public void SchemeTypeKindAndOAuthTypeSetCorrectly() + { + // Arrange + OAuth2AuthCode authCode = new OAuth2AuthCode(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.OAuth2, authCode.SchemeType); + Assert.Equal(OAuth2Type.AuthCode, authCode.OAuth2Type); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new OAuth2AuthCode().Initialize(record: null)); + } + + [Fact] + public void InitializeOAuth2AuthCodeWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("TokenUrl", new EdmStringConstant("http://tokenUrl")), + new EdmPropertyConstructor("AuthorizationUrl", new EdmStringConstant("http://authorizationUrl"))); + + OAuth2AuthCode authCode = new OAuth2AuthCode(); + Assert.Null(authCode.Name); + Assert.Null(authCode.Description); + Assert.Null(authCode.Scopes); + Assert.Null(authCode.AuthorizationUrl); + Assert.Null(authCode.TokenUrl); + + // Act + authCode.Initialize(record); + + // Assert + Assert.Null(authCode.Name); + Assert.Null(authCode.Description); + Assert.Null(authCode.Scopes); + Assert.Equal("http://authorizationUrl", authCode.AuthorizationUrl); + Assert.Equal("http://tokenUrl", authCode.TokenUrl); + } + + [Fact] + public void InitializeOAuth2AuthCodeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + OAuth2AuthCode authoCode = model.GetRecord(model.EntityContainer, "NS.MyOAuth2AuthCode"); + + // Assert + Assert.Null(authoCode.Name); + Assert.Null(authoCode.Description); + Assert.Null(authoCode.Scopes); + Assert.Equal("http://tokenUrl", authoCode.TokenUrl); + Assert.Equal("http://authorizationUrl", authoCode.AuthorizationUrl); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ClientCredentialsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ClientCredentialsTests.cs new file mode 100644 index 0000000..898cd41 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ClientCredentialsTests.cs @@ -0,0 +1,105 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class OAuth2ClientCredentialsTests + { + [Fact] + public void SchemeTypeKindAndOAuthTypeSetCorrectly() + { + // Arrange + OAuth2ClientCredentials credentials = new OAuth2ClientCredentials(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.OAuth2, credentials.SchemeType); + Assert.Equal(OAuth2Type.ClientCredentials, credentials.OAuth2Type); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new OAuth2ClientCredentials().Initialize(record: null)); + } + + [Fact] + public void InitializeOAuth2ClientCredentialsWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("TokenUrl", new EdmStringConstant("http://tokenUrl"))); + + OAuth2ClientCredentials credentials = new OAuth2ClientCredentials(); + Assert.Null(credentials.Name); + Assert.Null(credentials.Description); + Assert.Null(credentials.Scopes); + Assert.Null(credentials.TokenUrl); + + // Act + credentials.Initialize(record); + + // Assert + Assert.Null(credentials.Name); + Assert.Null(credentials.Description); + Assert.Null(credentials.Scopes); + Assert.Equal("http://tokenUrl", credentials.TokenUrl); + } + + [Fact] + public void InitializeOAuth2ClientCredentialsWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + OAuth2ClientCredentials credentials = model.GetRecord(model.EntityContainer, "NS.MyOAuth2ClientCredentials"); + + // Assert + Assert.Null(credentials.Name); + Assert.Null(credentials.Description); + Assert.Null(credentials.Scopes); + Assert.Equal("http://tokenUrl", credentials.TokenUrl); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ImplicitTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ImplicitTests.cs new file mode 100644 index 0000000..51ac1b6 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2ImplicitTests.cs @@ -0,0 +1,105 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class OAuth2ImplicitTests + { + [Fact] + public void SchemeTypeKindAndOAuthTypeSetCorrectly() + { + // Arrange + OAuth2Implicit oAuthImplicit = new OAuth2Implicit(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.OAuth2, oAuthImplicit.SchemeType); + Assert.Equal(OAuth2Type.Implicit, oAuthImplicit.OAuth2Type); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new OAuth2Implicit().Initialize(record: null)); + } + + [Fact] + public void InitializeOAuth2ImplicitWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("AuthorizationUrl", new EdmStringConstant("http://authorizationUrl"))); + + OAuth2Implicit oAuthImplicit = new OAuth2Implicit(); + Assert.Null(oAuthImplicit.Name); + Assert.Null(oAuthImplicit.Description); + Assert.Null(oAuthImplicit.Scopes); + Assert.Null(oAuthImplicit.AuthorizationUrl); + + // Act + oAuthImplicit.Initialize(record); + + // Assert + Assert.Null(oAuthImplicit.Name); + Assert.Null(oAuthImplicit.Description); + Assert.Null(oAuthImplicit.Scopes); + Assert.Equal("http://authorizationUrl", oAuthImplicit.AuthorizationUrl); + } + + [Fact] + public void InitializeOAuth2ImplicitWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + OAuth2Implicit oAuthImplicit = model.GetRecord(model.EntityContainer, "NS.MyOAuth2Implicit"); + + // Assert + Assert.Null(oAuthImplicit.Name); + Assert.Null(oAuthImplicit.Description); + Assert.Null(oAuthImplicit.Scopes); + Assert.Equal("http://authorizationUrl", oAuthImplicit.AuthorizationUrl); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2PasswordTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2PasswordTests.cs new file mode 100644 index 0000000..d193f07 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OAuth2PasswordTests.cs @@ -0,0 +1,110 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class OAuth2PasswordTests + { + [Fact] + public void SchemeTypeKindAndOAuthTypeSetCorrectly() + { + // Arrange + OAuth2Password password = new OAuth2Password(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.OAuth2, password.SchemeType); + Assert.Equal(OAuth2Type.Pasword, password.OAuth2Type); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new OAuth2Password().Initialize(record: null)); + } + + [Fact] + public void InitializeOAuth2PasswordWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("RefreshUrl", new EdmStringConstant("http://refreshUrl")), + new EdmPropertyConstructor("TokenUrl", new EdmStringConstant("http://tokenUrl"))); + + OAuth2Password password = new OAuth2Password(); + Assert.Null(password.Name); + Assert.Null(password.Description); + Assert.Null(password.Scopes); + Assert.Null(password.RefreshUrl); + Assert.Null(password.TokenUrl); + + // Act + password.Initialize(record); + + // Assert + Assert.Null(password.Name); + Assert.Null(password.Description); + Assert.Null(password.Scopes); + Assert.Equal("http://refreshUrl", password.RefreshUrl); + Assert.Equal("http://tokenUrl", password.TokenUrl); + } + + [Fact] + public void InitializeOAuth2PasswordWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + OAuth2Password password = model.GetRecord(model.EntityContainer, "NS.MyOAuth2Password"); + + // Assert + Assert.Null(password.Name); + Assert.Null(password.Description); + Assert.Null(password.Scopes); + Assert.Equal("http://refreshUrl", password.RefreshUrl); + Assert.Equal("http://tokenUrl", password.TokenUrl); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OpenIDConnectTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OpenIDConnectTests.cs new file mode 100644 index 0000000..f97f97b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/OpenIDConnectTests.cs @@ -0,0 +1,102 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class OpenIDConnectTests + { + [Fact] + public void SchemeTypeKindSetCorrectly() + { + // Arrange + OpenIDConnect openIDConnect = new OpenIDConnect(); + + // Act & Assert + Assert.Equal(SecuritySchemeType.OpenIdConnect, openIDConnect.SchemeType); + } + + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new OpenIDConnect().Initialize(record: null)); + } + + [Fact] + public void InitializeOpenIDConnectWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("OpenIDConnectWork")), + new EdmPropertyConstructor("IssuerUrl", new EdmStringConstant("http://any"))); + + OpenIDConnect idConnection = new OpenIDConnect(); + Assert.Null(idConnection.Name); + Assert.Null(idConnection.Description); + Assert.Null(idConnection.IssuerUrl); + + // Act + idConnection.Initialize(record); + + // Assert + Assert.Equal("OpenIDConnectWork", idConnection.Name); + Assert.Null(idConnection.Description); + Assert.Equal("http://any", idConnection.IssuerUrl); + } + + [Fact] + public void InitializeOpenIDConnectWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + OpenIDConnect idConnection = model.GetRecord(model.EntityContainer, "NS.MyOpenIDConnect"); + + // Assert + Assert.Null(idConnection.Name); + Assert.Null(idConnection.Description); + Assert.Equal("http://any", idConnection.IssuerUrl); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/SecuritySchemeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/SecuritySchemeTests.cs new file mode 100644 index 0000000..0616a57 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Authorization/SecuritySchemeTests.cs @@ -0,0 +1,133 @@ +// ------------------------------------------------------------ +// 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 System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Authorization; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Authorization.Tests +{ + public class SecuritySchemeTests + { + [Fact] + public void InitializeThrowArgumentNullRecord() + { + // Arrange & Act & Assert + Assert.Throws("record", () => new SecurityScheme().Initialize(record: null)); + } + + [Fact] + public void TermAttributeAttachedOnSecurityScheme() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Authorization.V1.SecuritySchemes", qualifiedName); + } + + [Fact] + public void InitializeSecuritySchemeWithRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Authorization", new EdmStringConstant("DelegatedWork")), + new EdmPropertyConstructor("RequiredScopes", new EdmCollectionExpression( + new EdmStringConstant("User.ReadAll"), + new EdmStringConstant("User.WriteAll")))); + + SecurityScheme securityScheme = new SecurityScheme(); + Assert.Null(securityScheme.Authorization); + Assert.Null(securityScheme.RequiredScopes); + + // Act + securityScheme.Initialize(record); + + // Assert + Assert.NotNull(securityScheme.Authorization); + Assert.Equal("DelegatedWork", securityScheme.Authorization); + + Assert.NotNull(securityScheme.RequiredScopes); + Assert.Equal(2, securityScheme.RequiredScopes.Count); + Assert.Equal(new[] { "User.ReadAll", "User.WriteAll" }, securityScheme.RequiredScopes); + } + + [Fact] + public void InitializeSecuritySchemeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + User.ReadAll + User.WriteAll + + + + + + + + Directory.ReadAll + Directory.WriteAll + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + SecurityScheme[] schemes = model.GetCollection(model.EntityContainer).ToArray(); + + // Assert + Assert.NotNull(schemes); + Assert.Equal(2, schemes.Length); + + // #1 + Assert.Equal("DelegatedWork", schemes[0].Authorization); + Assert.Equal(2, schemes[0].RequiredScopes.Count); + Assert.Equal(new[] { "User.ReadAll", "User.WriteAll" }, schemes[0].RequiredScopes); + + // #2 + Assert.Equal("DelegatedPersonal", schemes[1].Authorization); + Assert.Equal(2, schemes[1].RequiredScopes.Count); + Assert.Equal(new[] { "Directory.ReadAll", "Directory.WriteAll" }, schemes[1].RequiredScopes); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/BatchSupportedTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/BatchSupportedTests.cs similarity index 98% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/BatchSupportedTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/BatchSupportedTests.cs index 2a970cb..11d472f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/BatchSupportedTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/BatchSupportedTests.cs @@ -6,11 +6,11 @@ using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; using Microsoft.OData.Edm.Vocabularies; -using Microsoft.OpenApi.OData.Capabilities; using Xunit; namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests { +#if false public class BatchSupportedTests { [Fact] @@ -76,4 +76,5 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests return model; } } +#endif } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CapabilitiesModelHelper.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CapabilitiesModelHelper.cs similarity index 97% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CapabilitiesModelHelper.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CapabilitiesModelHelper.cs index 899c760..4d04ed7 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/CapabilitiesModelHelper.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CapabilitiesModelHelper.cs @@ -7,7 +7,7 @@ using System.Xml.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { public class CapabilitiesModelHelper { @@ -109,6 +109,7 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests + {3} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CollectionPropertyRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CollectionPropertyRestrictionsTypeTests.cs new file mode 100644 index 0000000..e65ce6f --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CollectionPropertyRestrictionsTypeTests.cs @@ -0,0 +1,78 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class CollectionPropertyRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnCollectionPropertyRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.CollectionPropertyRestrictions", qualifiedName); + } + + [Fact] + public void InitializeCollectionPropertyRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("CollectionProperty", new EdmPropertyPathExpression("abc/xyz")), + new EdmPropertyConstructor("FilterFunctions", new EdmCollectionExpression(new EdmStringConstant("div"))), + new EdmPropertyConstructor("FilterRestrictions", new EdmRecordExpression(new EdmPropertyConstructor("Filterable", new EdmBooleanConstant(true)))), + new EdmPropertyConstructor("SearchRestrictions", new EdmRecordExpression(new EdmPropertyConstructor("Searchable", new EdmBooleanConstant(false)))), + new EdmPropertyConstructor("SortRestrictions", new EdmRecordExpression(new EdmPropertyConstructor("Sortable", new EdmBooleanConstant(false)))), + new EdmPropertyConstructor("TopSupported", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("Deletable", new EdmBooleanConstant(false)) + // SkipSupported + // SelectSupport + // Insertable + // Updatable + ); + + // Act + CollectionPropertyRestrictionsType collectionPropertyRestrictions = new CollectionPropertyRestrictionsType(); + collectionPropertyRestrictions.Initialize(record); + + // Assert + Assert.Null(collectionPropertyRestrictions.SkipSupported); + Assert.Null(collectionPropertyRestrictions.SelectSupport); + Assert.Null(collectionPropertyRestrictions.Insertable); + Assert.Null(collectionPropertyRestrictions.Updatable); + + Assert.Equal("abc/xyz", collectionPropertyRestrictions.CollectionProperty); + + Assert.NotNull(collectionPropertyRestrictions.FilterFunctions); + string function = Assert.Single(collectionPropertyRestrictions.FilterFunctions); + Assert.Equal("div", function); + + Assert.NotNull(collectionPropertyRestrictions.FilterRestrictions); + Assert.NotNull(collectionPropertyRestrictions.FilterRestrictions.Filterable); + Assert.True(collectionPropertyRestrictions.FilterRestrictions.Filterable.Value); + + Assert.NotNull(collectionPropertyRestrictions.SearchRestrictions); + Assert.NotNull(collectionPropertyRestrictions.SearchRestrictions.Searchable); + Assert.False(collectionPropertyRestrictions.SearchRestrictions.Searchable.Value); + + Assert.NotNull(collectionPropertyRestrictions.SortRestrictions); + Assert.NotNull(collectionPropertyRestrictions.SortRestrictions.Sortable); + Assert.False(collectionPropertyRestrictions.SortRestrictions.Sortable.Value); + + Assert.NotNull(collectionPropertyRestrictions.TopSupported); + Assert.True(collectionPropertyRestrictions.TopSupported.Value); + + Assert.NotNull(collectionPropertyRestrictions.Deletable); + Assert.False(collectionPropertyRestrictions.Deletable.Value); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CountRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CountRestrictionsTypeTests.cs new file mode 100644 index 0000000..1ca2e19 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CountRestrictionsTypeTests.cs @@ -0,0 +1,107 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class CountRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnCountRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.CountRestrictions", qualifiedName); + } + + [Fact] + public void InitializeCountRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Countable", new EdmBooleanConstant(false) ), + new EdmPropertyConstructor("NonCountableProperties", new EdmCollectionExpression( + new EdmPropertyPathExpression("Emails"), + new EdmPropertyPathExpression("mij"))), + new EdmPropertyConstructor("NonCountableNavigationProperties", new EdmCollectionExpression( + new EdmNavigationPropertyPathExpression("RelatedEvents"), + new EdmNavigationPropertyPathExpression("abc"))) + ); + + // Act + CountRestrictionsType count = new CountRestrictionsType(); + count.Initialize(record); + + // Assert + VerifyCountRestrictions(count); + } + + [Fact] + public void InitializeCountRestrictionsWorksWithCsdl() + { + // Arrange + string countAnnotation = @" + + + + + + Emails + mij + + + + + RelatedEvents + abc + + + + "; + + IEdmModel model = CapabilitiesModelHelper.GetEdmModelSetInline(countAnnotation); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + CountRestrictionsType count = model.GetRecord(calendars); + + // Assert + VerifyCountRestrictions(count); + } + + private static void VerifyCountRestrictions(CountRestrictionsType count) + { + Assert.NotNull(count); + + Assert.NotNull(count.Countable); + Assert.False(count.Countable.Value); + Assert.False(count.IsCountable); + + Assert.NotNull(count.NonCountableProperties); + Assert.Equal(2, count.NonCountableProperties.Count); + Assert.Equal("Emails|mij", String.Join("|", count.NonCountableProperties)); + + Assert.NotNull(count.NonCountableNavigationProperties); + Assert.Equal(2, count.NonCountableNavigationProperties.Count); + Assert.Equal("RelatedEvents,abc", String.Join(",", count.NonCountableNavigationProperties)); + + Assert.False(count.IsNonCountableProperty("id")); + Assert.True(count.IsNonCountableProperty("Emails")); + Assert.True(count.IsNonCountableNavigationProperty("RelatedEvents")); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CustomParameterTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CustomParameterTests.cs new file mode 100644 index 0000000..b37f694 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/CustomParameterTests.cs @@ -0,0 +1,126 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.IO; +using System.Xml; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Microsoft.OpenApi.OData.Vocabulary.Core; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class CustomParameterTests + { + [Fact] + public void InitializeCustomParameterWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("odata-debug")), + new EdmPropertyConstructor("Description", new EdmStringConstant("Debug support for OData services")), + new EdmPropertyConstructor("DocumentationURL", new EdmStringConstant("https://debug.html")), + new EdmPropertyConstructor("Required", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("ExampleValues", + new EdmCollectionExpression( + new EdmRecordExpression(new EdmPropertyConstructor("Value", new EdmStringConstant("html"))), + new EdmRecordExpression(new EdmPropertyConstructor("Value", new EdmTimeOfDayConstant(new TimeOfDay(3, 4, 5, 6))))))); + + // Act + CustomParameter parameter = new CustomParameter(); + parameter.Initialize(record); + + // Assert + VerifyCustomParameter(parameter); + } + + [Fact] + public void InitializeCountRestrictionsWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + + + + + + + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + CustomParameter count = model.GetRecord(model.EntityContainer, "NS.MyCustomParameter"); + + // Assert + VerifyCustomParameter(count); + } + + private static void VerifyCustomParameter(CustomParameter parameter) + { + Assert.NotNull(parameter); + + Assert.NotNull(parameter.Name); + Assert.Equal("odata-debug", parameter.Name); + + Assert.NotNull(parameter.Description); + Assert.Equal("Debug support for OData services", parameter.Description); + + Assert.NotNull(parameter.DocumentationURL); + Assert.Equal("https://debug.html", parameter.DocumentationURL); + + Assert.NotNull(parameter.Required); + Assert.False(parameter.Required.Value); + + Assert.NotNull(parameter.ExampleValues); + Assert.Equal(2, parameter.ExampleValues.Count); + + // #1 + PrimitiveExampleValue value = parameter.ExampleValues[0]; + Assert.Null(value.Description); + Assert.NotNull(value.Value); + Assert.Equal("html", value.Value.Value); + + // #2 + value = parameter.ExampleValues[1]; + Assert.Null(value.Description); + Assert.NotNull(value.Value); + Assert.Equal(new TimeOfDay(3, 4, 5, 6), value.Value.Value); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + {0} + + + +"; + string schema = string.Format(template, annotation); + + IEdmModel model; + bool result = SchemaReader.TryParse(new XmlReader[] { XmlReader.Create(new StringReader(schema)) }, out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepInsertSupportTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepInsertSupportTypeTests.cs new file mode 100644 index 0000000..b9e8fc5 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepInsertSupportTypeTests.cs @@ -0,0 +1,79 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class DeepInsertSupportTypeTests + { + [Fact] + public void TermAttributeAttachedOnDeepInsertSupportType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.DeepInsertSupport", qualifiedName); + } + + [Fact] + public void InitializeDeepInsertSupportTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Supported", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("ContentIDSupported", new EdmBooleanConstant(true))); + + // Act + DeepInsertSupportType deepInsert = new DeepInsertSupportType(); + deepInsert.Initialize(record); + + // Assert + VerifyDeepInsertSupportType(deepInsert); + } + + [Fact] + public void InitializeDeepInsertSupportTypeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + "; + + IEdmModel model = CapabilitiesModelHelper.GetEdmModelSetInline(annotation); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + DeepInsertSupportType deepInsert = model.GetRecord(calendars); + + // Assert + VerifyDeepInsertSupportType(deepInsert); + } + + private static void VerifyDeepInsertSupportType(DeepInsertSupportType deepInsert) + { + Assert.NotNull(deepInsert); + + Assert.NotNull(deepInsert.Supported); + Assert.False(deepInsert.Supported.Value); + + Assert.NotNull(deepInsert.ContentIDSupported); + Assert.True(deepInsert.ContentIDSupported.Value); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepUpdateSupportTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepUpdateSupportTypeTests.cs new file mode 100644 index 0000000..e1aba36 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeepUpdateSupportTypeTests.cs @@ -0,0 +1,79 @@ +// ------------------------------------------------------------ +// 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.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class DeepUpdateSupportTypeTests + { + [Fact] + public void TermAttributeAttachedOnDeepUpdateSupportType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.DeepUpdateSupport", qualifiedName); + } + + [Fact] + public void InitializeDeepUpdateSupportTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Supported", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("ContentIDSupported", new EdmBooleanConstant(true))); + + // Act + DeepUpdateSupportType deepUpdate = new DeepUpdateSupportType(); + deepUpdate.Initialize(record); + + // Assert + VerifyDeepUpdateSupportType(deepUpdate); + } + + [Fact] + public void InitializeDeepUpdateSupportTypeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + "; + + IEdmModel model = CapabilitiesModelHelper.GetEdmModelSetInline(annotation); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + DeepUpdateSupportType deepUpdate = model.GetRecord(calendars); + + // Assert + VerifyDeepUpdateSupportType(deepUpdate); + } + + private static void VerifyDeepUpdateSupportType(DeepUpdateSupportType deepUpdate) + { + Assert.NotNull(deepUpdate); + + Assert.NotNull(deepUpdate.Supported); + Assert.False(deepUpdate.Supported.Value); + + Assert.NotNull(deepUpdate.ContentIDSupported); + Assert.True(deepUpdate.ContentIDSupported.Value); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeleteRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeleteRestrictionsTypeTests.cs new file mode 100644 index 0000000..916e97b --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/DeleteRestrictionsTypeTests.cs @@ -0,0 +1,171 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class DeleteRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnDeleteRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.DeleteRestrictions", qualifiedName); + } + + [Fact] + public void InitializeDeleteRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Deletable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("NonDeletableNavigationProperties", + new EdmCollectionExpression(new EdmNavigationPropertyPathExpression("abc"), new EdmNavigationPropertyPathExpression("RelatedEvents"))), + new EdmPropertyConstructor("MaxLevels", new EdmIntegerConstant(42)), + new EdmPropertyConstructor("Permission", new EdmRecordExpression( + new EdmPropertyConstructor("Scheme", new EdmRecordExpression(new EdmPropertyConstructor("Authorization", new EdmStringConstant("schemeName")))))), + new EdmPropertyConstructor("CustomQueryOptions", new EdmCollectionExpression( + new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("odata-debug")), + new EdmPropertyConstructor("DocumentationURL", new EdmStringConstant("https://debug.html"))))) + // CustomHeaders + ); + + // Act + DeleteRestrictionsType delete = new DeleteRestrictionsType(); + delete.Initialize(record); + + // Assert + VerifyDeleteRestrictionsType(delete); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntityTypeReturnsCorrectDeleteRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + DeleteRestrictionsType delete = model.GetRecord(calendars); + + // Assert + VerifyDeleteRestrictionsType(delete); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntitySetReturnsCorrectDeleteRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + DeleteRestrictionsType delete = model.GetRecord(calendars); + + // Assert + VerifyDeleteRestrictionsType(delete); + } + + private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) + { + string annotation = @" + + + + + + abc + RelatedEvents + + + + + + + + + + + + + + + + + + + + + + "; + + if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) + { + annotation = string.Format(template, annotation); + return CapabilitiesModelHelper.GetEdmModelOutline(annotation); + } + else + { + return CapabilitiesModelHelper.GetEdmModelTypeInline(annotation); + } + } + + private static void VerifyDeleteRestrictionsType(DeleteRestrictionsType delete) + { + Assert.NotNull(delete); + + Assert.NotNull(delete.Deletable); + Assert.False(delete.Deletable.Value); + + Assert.NotNull(delete.NonDeletableNavigationProperties); + Assert.Equal(2, delete.NonDeletableNavigationProperties.Count); + Assert.Equal("abc|RelatedEvents", String.Join("|", delete.NonDeletableNavigationProperties)); + + Assert.True(delete.IsNonDeletableNavigationProperty("RelatedEvents")); + + Assert.NotNull(delete.Permission); + Assert.Equal("schemeName", delete.Permission.Scheme.Authorization); + + Assert.Null(delete.CustomHeaders); + + Assert.NotNull(delete.CustomQueryOptions); + CustomParameter parameter = Assert.Single(delete.CustomQueryOptions); + Assert.Equal("odata-debug", parameter.Name); + Assert.Equal("https://debug.html", parameter.DocumentationURL); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/ExpandRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ExpandRestrictionsTypeTests.cs similarity index 70% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/ExpandRestrictionsTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ExpandRestrictionsTypeTests.cs index 83c5182..039b9e0 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/ExpandRestrictionsTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ExpandRestrictionsTypeTests.cs @@ -6,39 +6,43 @@ using System; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using Xunit; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { - public class ExpandRestrictionsTests + public class ExpandRestrictionsTypeTests { [Fact] - public void KindPropertyReturnsExpandRestrictionsEnumMember() + public void TermAttributeAttachedOnExpandRestrictionsType() { // Arrange & Act - ExpandRestrictions expand = new ExpandRestrictions(); + string qualifiedName = Utils.GetTermQualifiedName(); // Assert - Assert.Equal(CapabilitesTermKind.ExpandRestrictions, expand.Kind); + Assert.Equal("Org.OData.Capabilities.V1.ExpandRestrictions", qualifiedName); } [Fact] - public void UnknownAnnotatableTargetReturnsDefaultExpandRestrictionsValues() + public void InitializeExpandRestrictionsTypeWithRecordSuccess() { - // Arrange - ExpandRestrictions expand = new ExpandRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Expandable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("NonExpandableProperties", + new EdmCollectionExpression(new EdmNavigationPropertyPathExpression("abc"), new EdmNavigationPropertyPathExpression("RelatedEvents"))), + new EdmPropertyConstructor("MaxLevels", new EdmIntegerConstant(42)) + ); - // Act - bool result = expand.Load(EdmCoreModel.Instance, entityType); + // Act + ExpandRestrictionsType expand = new ExpandRestrictionsType(); + expand.Initialize(record); // Assert - Assert.False(result); - Assert.Equal(CapabilitesTermKind.ExpandRestrictions, expand.Kind); - Assert.True(expand.IsExpandable); - Assert.Null(expand.Expandable); - Assert.Null(expand.NonExpandableProperties); + VerifyExpandRestrictions(expand); } [Theory] @@ -59,11 +63,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendars); // guard // Act - ExpandRestrictions expand = new ExpandRestrictions(); - bool result = expand.Load(model, calendars); + ExpandRestrictionsType expand = model.GetRecord(calendars); // Assert - Assert.True(result); VerifyExpandRestrictions(expand); } @@ -85,12 +87,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendars); // guard // Act - // Act - ExpandRestrictions expand = new ExpandRestrictions(); - bool result = expand.Load(model, calendars); + ExpandRestrictionsType expand = model.GetRecord(calendars); // Assert - Assert.True(result); VerifyExpandRestrictions(expand); } @@ -100,6 +99,7 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests + abc @@ -120,13 +120,16 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests } } - private static void VerifyExpandRestrictions(ExpandRestrictions expand) + private static void VerifyExpandRestrictions(ExpandRestrictionsType expand) { Assert.NotNull(expand); Assert.NotNull(expand.Expandable); Assert.False(expand.Expandable.Value); + Assert.NotNull(expand.MaxLevels); + Assert.Equal(42, expand.MaxLevels.Value); + Assert.NotNull(expand.NonExpandableProperties); Assert.Equal(2, expand.NonExpandableProperties.Count); Assert.Equal("abc|RelatedEvents", String.Join("|", expand.NonExpandableProperties)); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/FilterRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/FilterRestrictionsTypeTests.cs similarity index 62% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/FilterRestrictionsTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/FilterRestrictionsTypeTests.cs index e407937..a55d2fe 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/FilterRestrictionsTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/FilterRestrictionsTypeTests.cs @@ -6,46 +6,52 @@ using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using Xunit; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { - public class FilterRestrictionsTests + public class FilterRestrictionsTypeTests { [Fact] - public void KindPropertyReturnsFilterRestrictionsEnumMember() + public void TermAttributeAttachedOnFilterRestrictionsType() { // Arrange & Act - FilterRestrictions filter = new FilterRestrictions(); + string qualifiedName = Utils.GetTermQualifiedName(); // Assert - Assert.Equal(CapabilitesTermKind.FilterRestrictions, filter.Kind); + Assert.Equal("Org.OData.Capabilities.V1.FilterRestrictions", qualifiedName); } [Fact] - public void UnknownAnnotatableTargetReturnsDefaultFilterRestrictionsValues() + public void InitializFilterRestrictionsTypeWithRecordSuccess() { - // Arrange - FilterRestrictions filter = new FilterRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Filterable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("RequiresFilter", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("RequiredProperties", new EdmCollectionExpression(new EdmPropertyPathExpression("Id"))), + new EdmPropertyConstructor("NonFilterableProperties", new EdmCollectionExpression(new EdmPropertyPathExpression("Emails"))), + new EdmPropertyConstructor("FilterExpressionRestrictions", new EdmCollectionExpression( + new EdmRecordExpression(new EdmPropertyConstructor("Property", new EdmPropertyPathExpression("RelatedProperty"))))), + new EdmPropertyConstructor("MaxLevels", new EdmIntegerConstant(42)) + ); - // Act - bool result = filter.Load(EdmCoreModel.Instance, entityType); + // Act + FilterRestrictionsType filter = new FilterRestrictionsType(); + filter.Initialize(record); // Assert - Assert.False(result); - Assert.True(filter.IsFilterable); - Assert.Null(filter.Filterable); - Assert.Null(filter.RequiresFilter); - Assert.Null(filter.RequiredProperties); - Assert.Null(filter.NonFilterableProperties); + VerifyFilterRestrictions(filter); } [Theory] [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] - public void TargetOnEntityTypeReturnsCorrectfilterRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + public void TargetOnEntityTypeReturnsCorrectFilterRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) { // Arrange const string template = @" @@ -60,11 +66,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendars); // guard // Act - FilterRestrictions filter = new FilterRestrictions(); - bool result = filter.Load(model, calendars); + FilterRestrictionsType filter = model.GetRecord(calendars); // Assert - Assert.True(result); VerifyFilterRestrictions(filter); } @@ -86,11 +90,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendars); // guard // Act - FilterRestrictions filter = new FilterRestrictions(); - bool result = filter.Load(model, calendars); + FilterRestrictionsType filter = model.GetRecord(calendars); // Assert - Assert.True(result); VerifyFilterRestrictions(filter); } @@ -101,6 +103,7 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests + Id @@ -111,6 +114,13 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Emails + + + + + + + "; @@ -125,7 +135,7 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests } } - private static void VerifyFilterRestrictions(FilterRestrictions filter) + private static void VerifyFilterRestrictions(FilterRestrictionsType filter) { Assert.NotNull(filter); @@ -143,6 +153,13 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.Single(filter.NonFilterableProperties); Assert.Equal("Emails", filter.NonFilterableProperties.First()); + Assert.NotNull(filter.MaxLevels); + Assert.Equal(42, filter.MaxLevels.Value); + + Assert.NotNull(filter.FilterExpressionRestrictions); + FilterExpressionRestrictionType express = Assert.Single(filter.FilterExpressionRestrictions); + Assert.Equal("RelatedProperty", express.Property); + Assert.True(filter.IsRequiredProperty("Id")); Assert.False(filter.IsRequiredProperty("ID")); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/InsertRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/InsertRestrictionsTypeTests.cs new file mode 100644 index 0000000..c16818c --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/InsertRestrictionsTypeTests.cs @@ -0,0 +1,193 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Microsoft.OpenApi.OData.Vocabulary.Core; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class InsertRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnInsertRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.InsertRestrictions", qualifiedName); + } + + [Fact] + public void InitializInsertRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression primitiveExampleValue = new EdmRecordExpression( + new EdmPropertyConstructor("Description", new EdmStringConstant("example desc")), + new EdmPropertyConstructor("Value", new EdmStringConstant("example value"))); + + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Insertable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("NonInsertableProperties", new EdmCollectionExpression(new EdmPathExpression("abc/xyz"))), + new EdmPropertyConstructor("NonInsertableNavigationProperties", new EdmCollectionExpression(new EdmNavigationPropertyPathExpression("abc"), new EdmNavigationPropertyPathExpression("RelatedEvents"))), + new EdmPropertyConstructor("MaxLevels", new EdmIntegerConstant(8)), + new EdmPropertyConstructor("CustomQueryOptions", new EdmCollectionExpression( + new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("primitive name")), + new EdmPropertyConstructor("Description", new EdmStringConstant("primitive desc")), + new EdmPropertyConstructor("DocumentationURL", new EdmStringConstant("http://any3")), + new EdmPropertyConstructor("Required", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("ExampleValues", new EdmCollectionExpression(primitiveExampleValue))))) + // QueryOptions + // Permission + // CustomHeaders + ); + + // Act + InsertRestrictionsType insert = new InsertRestrictionsType(); + insert.Initialize(record); + + // Assert + VerifyInsertRestrictions(insert); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntityTypeReturnsCorrectInsertRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + InsertRestrictionsType insert = model.GetRecord(calendars); + + // Assert + VerifyInsertRestrictions(insert); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntitySetReturnsCorrectInsertRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + InsertRestrictionsType insert = model.GetRecord(calendars); + + // Assert + VerifyInsertRestrictions(insert); + } + + private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) + { + string countAnnotation = @" + + + + + + abc/xyz + + + + + abc + RelatedEvents + + + + + + + + + + + + + + + + + + + + + + + "; + + if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) + { + countAnnotation = string.Format(template, countAnnotation); + return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); + } + else + { + return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); + } + } + + private static void VerifyInsertRestrictions(InsertRestrictionsType insert) + { + Assert.NotNull(insert); + + Assert.NotNull(insert.Insertable); + Assert.False(insert.Insertable.Value); + + Assert.NotNull(insert.NonInsertableNavigationProperties); + Assert.Equal(2, insert.NonInsertableNavigationProperties.Count); + Assert.Equal("abc|RelatedEvents", String.Join("|", insert.NonInsertableNavigationProperties)); + + Assert.True(insert.IsNonInsertableNavigationProperty("RelatedEvents")); + Assert.False(insert.IsNonInsertableNavigationProperty("MyUnknownNavigationProperty")); + + Assert.Null(insert.QueryOptions); + Assert.Null(insert.Permission); + Assert.Null(insert.CustomHeaders); + + Assert.NotNull(insert.MaxLevels); + Assert.Equal(8, insert.MaxLevels.Value); + + Assert.NotNull(insert.CustomQueryOptions); + CustomParameter parameter = Assert.Single(insert.CustomQueryOptions); + Assert.Equal("primitive name", parameter.Name); + Assert.Equal("http://any3", parameter.DocumentationURL); + + Assert.NotNull(parameter.ExampleValues); + PrimitiveExampleValue example = Assert.Single(parameter.ExampleValues); + Assert.Equal("example desc", example.Description); + Assert.Equal("example value", example.Value.Value); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/KeyAsSegmentSupportedTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/KeyAsSegmentSupportedTests.cs similarity index 59% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/KeyAsSegmentSupportedTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/KeyAsSegmentSupportedTests.cs index aa3f1ef..dc999d8 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/KeyAsSegmentSupportedTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/KeyAsSegmentSupportedTests.cs @@ -5,40 +5,15 @@ using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; using Microsoft.OData.Edm.Vocabularies; using Xunit; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Microsoft.OpenApi.OData.Edm; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { public class KeyAsSegmentSupportedTests { - [Fact] - public void KindPropertyReturnsKeyAsSegmentSupportedEnumMember() - { - // Arrange & Act - KeyAsSegmentSupported keyAsSegment = new KeyAsSegmentSupported(); - - // Assert - Assert.Equal(CapabilitesTermKind.KeyAsSegmentSupported, keyAsSegment.Kind); - } - - [Fact] - public void UnknownAnnotatableTargetReturnsDefaultTopSupportedValues() - { - // Arrange - KeyAsSegmentSupported keyAsSegment = new KeyAsSegmentSupported(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); - - // Act - bool result = keyAsSegment.Load(EdmCoreModel.Instance, entityType); - - // Assert - Assert.False(result); - Assert.True(keyAsSegment.IsSupported); - Assert.Null(keyAsSegment.Supported); - } - [Theory] [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline, true)] [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline, false)] @@ -51,13 +26,11 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(model); // guard // Act - KeyAsSegmentSupported KeyAsSegmentSupported = new KeyAsSegmentSupported(); - bool result = KeyAsSegmentSupported.Load(model, model.EntityContainer); + bool? result = model.GetBoolean(model.EntityContainer, CapabilitiesConstants.KeyAsSegmentSupported); // Assert - Assert.True(result); - Assert.NotNull(KeyAsSegmentSupported.Supported); - Assert.Equal(support, KeyAsSegmentSupported.Supported.Value); + Assert.NotNull(result); + Assert.Equal(support, result.Value); } private static IEdmModel GetEdmModel(EdmVocabularyAnnotationSerializationLocation location, bool supported) diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ModificationQueryOptionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ModificationQueryOptionsTypeTests.cs new file mode 100644 index 0000000..3c1ce16 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ModificationQueryOptionsTypeTests.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 System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class ModificationQueryOptionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnModificationQueryOptionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.ModificationQueryOptions", qualifiedName); + } + + [Fact] + public void InitializInsertRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("ExpandSupported", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("SelectSupported", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("ComputeSupported", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("FilterSupported", new EdmBooleanConstant(true)) + // SearchSupported + // SortSupported + ); + + // Act + ModificationQueryOptionsType query = new ModificationQueryOptionsType(); + query.Initialize(record); + + // Assert + VerifyModificationQueryOptions(query); + } + + [Fact] + public void InitializeModificationQueryOptionsTypeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + ModificationQueryOptionsType query = model.GetRecord(model.EntityContainer); + + // Assert + VerifyModificationQueryOptions(query); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + + private static void VerifyModificationQueryOptions(ModificationQueryOptionsType query) + { + Assert.NotNull(query); + + Assert.Null(query.SearchSupported); + Assert.Null(query.SortSupported); + + Assert.NotNull(query.ExpandSupported); + Assert.True(query.ExpandSupported); + + Assert.NotNull(query.SelectSupported); + Assert.True(query.SelectSupported); + + Assert.NotNull(query.ComputeSupported); + Assert.False(query.ComputeSupported); // false + + Assert.NotNull(query.FilterSupported); + Assert.True(query.FilterSupported); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/NavigationRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/NavigationRestrictionsTypeTests.cs similarity index 55% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/NavigationRestrictionsTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/NavigationRestrictionsTypeTests.cs index 4622a01..a16ac5f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/NavigationRestrictionsTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/NavigationRestrictionsTypeTests.cs @@ -6,38 +6,55 @@ using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using Xunit; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { - public class NavigationRestrictionsTests + public class NavigationRestrictionsTypeTests { [Fact] - public void KindPropertyReturnsNavigationRestrictionsEnumMember() + public void TermAttributeAttachedOnNavigationRestrictionsType() { // Arrange & Act - NavigationRestrictions navigation = new NavigationRestrictions(); + string qualifiedName = Utils.GetTermQualifiedName(); // Assert - Assert.Equal(CapabilitesTermKind.NavigationRestrictions, navigation.Kind); + Assert.Equal("Org.OData.Capabilities.V1.NavigationRestrictions", qualifiedName); } [Fact] - public void UnknownAnnotatableTargetReturnsDefaultPropertyValues() + public void InitializNavigationRestrictionsTypeWithRecordSuccess() { - // Arrange - NavigationRestrictions navigation = new NavigationRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); + // Assert + EdmModel model = new EdmModel(); + IEdmEnumType navigationType = model.FindType("Org.OData.Capabilities.V1.NavigationType") as IEdmEnumType; + Assert.NotNull(navigationType); - // Act - bool result = navigation.Load(EdmCoreModel.Instance, entityType); + IEdmRecordExpression restriction1 = new EdmRecordExpression( + new EdmPropertyConstructor("NavigationProperty", new EdmNavigationPropertyPathExpression("abc")), + new EdmPropertyConstructor("Navigability", new EdmEnumMemberExpression(navigationType.Members.First(c => c.Name == "Single"))), + new EdmPropertyConstructor("SkipSupported", new EdmBooleanConstant(false))); + + IEdmRecordExpression restriction2 = new EdmRecordExpression( + new EdmPropertyConstructor("NavigationProperty", new EdmNavigationPropertyPathExpression("xyz")), + new EdmPropertyConstructor("Navigability", new EdmEnumMemberExpression(navigationType.Members.First(c => c.Name == "None"))), + new EdmPropertyConstructor("OptimisticConcurrencyControl", new EdmBooleanConstant(true))); + + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Navigability", new EdmEnumMemberExpression(navigationType.Members.First(c => c.Name == "Recursive"))), + new EdmPropertyConstructor("RestrictedProperties", new EdmCollectionExpression(restriction1, restriction2)) + ); + + // Act + NavigationRestrictionsType navigation = new NavigationRestrictionsType(); + navigation.Initialize(record); // Assert - Assert.False(result); - Assert.True(navigation.IsNavigable); - Assert.Null(navigation.Navigability); - Assert.Null(navigation.RestrictedProperties); + VerifyNavigationRestrictions(navigation); } [Theory] @@ -46,57 +63,21 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests public void TargetOnEntityTypeReturnsCorrectNavigationRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) { // Arrange - const string outOfLineTemplate = @" + const string template = @" {0} "; - string navigationAnnotation = @" - - - - Org.OData.Capabilities.V1.NavigationType/Recursive - - - - - - Org.OData.Capabilities.V1.NavigationType/Single - - - - - - - "; - - IEdmModel model; - if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) - { - navigationAnnotation = string.Format(outOfLineTemplate, navigationAnnotation); - model = CapabilitiesModelHelper.GetEdmModelOutline(navigationAnnotation); - } - else - { - model = CapabilitiesModelHelper.GetEdmModelTypeInline(navigationAnnotation); - } + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); // Act - NavigationRestrictions navigation = new NavigationRestrictions(); - bool result = navigation.Load(model, calendars); + NavigationRestrictionsType navigation = model.GetRecord(calendars); // Assert - Assert.True(result); - Assert.NotNull(navigation.Navigability); - Assert.Equal(NavigationType.Recursive, navigation.Navigability.Value); - - Assert.NotNull(navigation.RestrictedProperties); - NavigationPropertyRestriction navRestriction = Assert.Single(navigation.RestrictedProperties); - Assert.NotNull(navRestriction.Navigability); - Assert.Equal(NavigationType.Single, navRestriction.Navigability.Value); - Assert.Equal("abc", navRestriction.NavigationProperty); + VerifyNavigationRestrictions(navigation); } [Theory] @@ -105,11 +86,31 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests public void TargetOnEntitySetReturnsCorrectNavigationRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) { // Arrange - const string outOfLineTemplate = @" + const string template = @" {0} "; + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + + // Act + NavigationRestrictionsType navigation = model.GetRecord(calendars); + + // Assert + VerifyNavigationRestrictions(navigation); + + NavigationPropertyRestriction navRestriction = navigation.RestrictedProperties.Last(); + Assert.NotNull(navRestriction.Navigability); + Assert.Equal(NavigationType.None, navRestriction.Navigability.Value); + Assert.Equal("xyz", navRestriction.NavigationProperty); + Assert.True(navigation.IsRestrictedProperty("xyz")); + } + + private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) + { string navigationAnnotation = @" @@ -120,47 +121,32 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests - Org.OData.Capabilities.V1.NavigationType/Single + Org.OData.Capabilities.V1.NavigationType/Single + Org.OData.Capabilities.V1.NavigationType/None + "; - IEdmModel model; if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) { - navigationAnnotation = string.Format(outOfLineTemplate, navigationAnnotation); - model = CapabilitiesModelHelper.GetEdmModelOutline(navigationAnnotation); + navigationAnnotation = string.Format(template, navigationAnnotation); + return CapabilitiesModelHelper.GetEdmModelOutline(navigationAnnotation); } else { - model = CapabilitiesModelHelper.GetEdmModelTypeInline(navigationAnnotation); + return CapabilitiesModelHelper.GetEdmModelTypeInline(navigationAnnotation); } - - IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); - - // Act - NavigationRestrictions navigation = new NavigationRestrictions(); - bool result = navigation.Load(model, calendars); - - // Assert - Assert.True(result); - VerifyNavigationRestrictions(navigation); - - NavigationPropertyRestriction navRestriction = navigation.RestrictedProperties.Last(); - Assert.NotNull(navRestriction.Navigability); - Assert.Equal(NavigationType.None, navRestriction.Navigability.Value); - Assert.Equal("xyz", navRestriction.NavigationProperty); - Assert.True(navigation.IsRestrictedProperty("xyz")); } [Fact] @@ -182,17 +168,14 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); // Act - NavigationRestrictions navigation = new NavigationRestrictions(); - bool result = navigation.Load(model, calendar); + NavigationRestrictionsType navigation = model.GetRecord(calendar); // Assert - - Assert.True(result); Assert.Null(navigation.Navigability); Assert.Null(navigation.RestrictedProperties); } - private static void VerifyNavigationRestrictions(NavigationRestrictions navigation) + private static void VerifyNavigationRestrictions(NavigationRestrictionsType navigation) { Assert.NotNull(navigation); Assert.True(navigation.IsNavigable); @@ -203,11 +186,32 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(navigation.RestrictedProperties); Assert.Equal(2, navigation.RestrictedProperties.Count); + Assert.False(navigation.IsRestrictedProperty("abc")); + Assert.True(navigation.IsRestrictedProperty("xyz")); + + // #1 NavigationPropertyRestriction navRestriction = navigation.RestrictedProperties.First(); Assert.NotNull(navRestriction.Navigability); Assert.Equal(NavigationType.Single, navRestriction.Navigability.Value); Assert.Equal("abc", navRestriction.NavigationProperty); - Assert.False(navigation.IsRestrictedProperty("abc")); + + Assert.NotNull(navRestriction.SkipSupported); + Assert.False(navRestriction.SkipSupported.Value); + + Assert.Null(navRestriction.TopSupported); + Assert.Null(navRestriction.OptimisticConcurrencyControl); + + // #2 + navRestriction = navigation.RestrictedProperties.Last(); + Assert.NotNull(navRestriction.Navigability); + Assert.Equal(NavigationType.None, navRestriction.Navigability.Value); + Assert.Equal("xyz", navRestriction.NavigationProperty); + + Assert.Null(navRestriction.SkipSupported); + Assert.Null(navRestriction.TopSupported); + + Assert.NotNull(navRestriction.OptimisticConcurrencyControl); + Assert.True(navRestriction.OptimisticConcurrencyControl.Value); } } } diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/OperationRestrictionTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/OperationRestrictionTypeTests.cs new file mode 100644 index 0000000..80f42f8 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/OperationRestrictionTypeTests.cs @@ -0,0 +1,123 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Linq; +using System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class OperationRestrictionTypeTests + { + [Fact] + public void TermAttributeAttachedOnOperationRestrictionType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.OperationRestrictions", qualifiedName); + } + + [Fact] + public void InitializOperationRestrictionTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("CustomHeaders", new EdmCollectionExpression( + new EdmRecordExpression( + new EdmPropertyConstructor("Name", new EdmStringConstant("head name")), + new EdmPropertyConstructor("Description", new EdmStringConstant("head desc")), + new EdmPropertyConstructor("DocumentationURL", new EdmStringConstant("http://any3")), + new EdmPropertyConstructor("Required", new EdmBooleanConstant(true))))) + // Permission + // CustomQueryOptions + ); + + // Act + OperationRestrictionType operation = new OperationRestrictionType(); + operation.Initialize(record); + + // Assert + VerifyOperationRestrictions(operation); + } + + [Fact] + public void InitializeModificationQueryOptionsTypeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + IEdmOperation edmOperation = model.SchemaElements.OfType().First(); + Assert.NotNull(edmOperation); + + // Act + OperationRestrictionType operation = model.GetRecord(edmOperation, "NS.MyOperationRestriction"); + + // Assert + VerifyOperationRestrictions(operation); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + + + {0} + + + + +"; + + string modelText = string.Format(template, annotation); + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + + private static void VerifyOperationRestrictions(OperationRestrictionType operation) + { + Assert.NotNull(operation); + + Assert.Null(operation.Permission); + Assert.Null(operation.CustomQueryOptions); + + Assert.NotNull(operation.CustomHeaders); + + CustomParameter parameter = Assert.Single(operation.CustomHeaders); + Assert.Equal("head name", parameter.Name); + Assert.Equal("http://any3", parameter.DocumentationURL); + Assert.Equal("head desc", parameter.Description); + Assert.True(parameter.Required.Value); + Assert.Null(parameter.ExampleValues); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/PermissionTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/PermissionTypeTests.cs new file mode 100644 index 0000000..f4751a1 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/PermissionTypeTests.cs @@ -0,0 +1,123 @@ +// ------------------------------------------------------------ +// 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.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class PermissionTypeTests + { + [Fact] + public void DefaultPropertyAsNull() + { + // Arrange & Act + PermissionType permission = new PermissionType(); + + // Assert + Assert.Null(permission.Scheme); + Assert.Null(permission.Scopes); + } + + [Fact] + public void InitializeWithNullRecordThrows() + { + // Arrange & Act + PermissionType permission = new PermissionType(); + + // Assert + Assert.Throws("record", () => permission.Initialize(record: null)); + } + + [Fact] + public void InitializeWithPermissionTypeRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Scheme", new EdmRecordExpression( + new EdmPropertyConstructor("Authorization", new EdmStringConstant("scheme name")))), + new EdmPropertyConstructor("Scopes", new EdmCollectionExpression(new EdmRecordExpression( + new EdmPropertyConstructor("Scope", new EdmStringConstant("scope name")))))); + + // Act + PermissionType permission = new PermissionType(); + permission.Initialize(record); + + // Assert + VerifyPermissionType(permission); + } + + [Fact] + public void ScopeTypeTermValueInitializeWorksForScopeType() + { + // Arrange + string annotation = @" + + + + + + + + + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + PermissionType permission = model.GetRecord(model.EntityContainer, "NS.MyTerm"); + + // Assert + VerifyPermissionType(permission); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + + private static void VerifyPermissionType(PermissionType permission) + { + Assert.NotNull(permission); + + Assert.NotNull(permission.Scheme); + Assert.Equal("scheme name", permission.Scheme.Authorization); + Assert.Null(permission.Scheme.RequiredScopes); + + Assert.NotNull(permission.Scopes); + ScopeType scope = Assert.Single(permission.Scopes); + Assert.Equal("scope name", scope.Scope); + Assert.Null(scope.RestrictedProperties); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ReadRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ReadRestrictionsTypeTests.cs new file mode 100644 index 0000000..32dd06f --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ReadRestrictionsTypeTests.cs @@ -0,0 +1,173 @@ +// ------------------------------------------------------------ +// 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.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class ReadRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnReadRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.ReadRestrictions", qualifiedName); + } + + [Fact] + public void InitializReadRestrictionsTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Readable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("CustomQueryOptions", new EdmCollectionExpression( + new EdmRecordExpression(new EdmPropertyConstructor("Name", new EdmStringConstant("root query name"))))), + // Root Permission + // Root CustomHeaders + new EdmPropertyConstructor("ReadByKeyRestrictions", new EdmRecordExpression( + new EdmPropertyConstructor("Readable", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("CustomHeaders", new EdmCollectionExpression( + new EdmRecordExpression(new EdmPropertyConstructor("Name", new EdmStringConstant("by key head name"))))) + // ByKey Permission + // ByKey CustomQueryOptions + )) + ); + + // Act + ReadRestrictionsType read = new ReadRestrictionsType(); + read.Initialize(record); + + // Assert + VerifyReadRestrictions(read); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntityTypeReturnsCorrectReadRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + ReadRestrictionsType read = model.GetRecord(calendars); + + // Assert + VerifyReadRestrictions(read); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntitySetReturnsCorrectReadRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + ReadRestrictionsType read = model.GetRecord(calendars); + + // Assert + VerifyReadRestrictions(read); + } + + private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) + { + string countAnnotation = @" + + + + + + + + + + + + + + + + + + + + + + + + "; + + if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) + { + countAnnotation = string.Format(template, countAnnotation); + return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); + } + else + { + return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); + } + } + + private static void VerifyReadRestrictions(ReadRestrictionsType read) + { + Assert.NotNull(read); + + Assert.NotNull(read.Readable); + Assert.False(read.Readable.Value); + + Assert.Null(read.Permission); + Assert.Null(read.CustomHeaders); + + Assert.NotNull(read.CustomQueryOptions); + CustomParameter parameter = Assert.Single(read.CustomQueryOptions); + Assert.Equal("root query name", parameter.Name); + Assert.Null(parameter.DocumentationURL); + Assert.Null(parameter.ExampleValues); + + // ReadByKeyRestrictions + Assert.NotNull(read.ReadByKeyRestrictions); + Assert.NotNull(read.ReadByKeyRestrictions.Readable); + Assert.True(read.ReadByKeyRestrictions.Readable.Value); + + Assert.Null(read.ReadByKeyRestrictions.Permission); + Assert.Null(read.ReadByKeyRestrictions.CustomQueryOptions); + + Assert.NotNull(read.ReadByKeyRestrictions.CustomHeaders); + parameter = Assert.Single(read.ReadByKeyRestrictions.CustomHeaders); + Assert.Equal("by key head name", parameter.Name); + Assert.Null(parameter.DocumentationURL); + Assert.Null(parameter.ExampleValues); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ScopeTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ScopeTypeTests.cs new file mode 100644 index 0000000..2190e4a --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/ScopeTypeTests.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; +using System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class ScopeTypeTests + { + [Fact] + public void DefaultPropertyAsNull() + { + // Arrange & Act + ScopeType scope = new ScopeType(); + + // Assert + Assert.Null(scope.Scope); + Assert.Null(scope.RestrictedProperties); + } + + [Fact] + public void InitializeWithNullRecordThrows() + { + // Arrange & Act + ScopeType scope = new ScopeType(); + + // Assert + Assert.Throws("record", () => scope.Initialize(record: null)); + } + + [Fact] + public void InitializeWithScopeTypeRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Scope", new EdmStringConstant("name")), + new EdmPropertyConstructor("RestrictedProperties", new EdmStringConstant("abc,xyz"))); + + // Act + ScopeType scope = new ScopeType(); + scope.Initialize(record); + + // Assert + Assert.NotNull(scope.Scope); + Assert.Equal("name", scope.Scope); + + Assert.NotNull(scope.RestrictedProperties); + Assert.Equal("abc,xyz", scope.RestrictedProperties); + } + + [Fact] + public void ScopeTypeTermValueInitializeWorksForScopeType() + { + // Arrange + string annotation = @" + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + // Act + ScopeType scope = model.GetRecord(model.EntityContainer, "NS.MyTerm"); + + // Assert + Assert.NotNull(scope); + Assert.Equal("name", scope.Scope); + Assert.NotNull(scope.RestrictedProperties); + Assert.Equal("abc,xyz", scope.RestrictedProperties); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SearchRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SearchRestrictionsTypeTests.cs similarity index 77% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SearchRestrictionsTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SearchRestrictionsTypeTests.cs index 93a962e..30f5eab 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SearchRestrictionsTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SearchRestrictionsTypeTests.cs @@ -5,38 +5,49 @@ using System.Linq; using Microsoft.OData.Edm; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using Xunit; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { - public class SearchRestrictionsTests + public class SearchRestrictionsTypeTests { [Fact] - public void KindPropertyReturnsSearchRestrictionsEnumMember() + public void TermAttributeAttachedOnSearchRestrictionsType() { // Arrange & Act - SearchRestrictions search = new SearchRestrictions(); + string qualifiedName = Utils.GetTermQualifiedName(); // Assert - Assert.Equal(CapabilitesTermKind.SearchRestrictions, search.Kind); + Assert.Equal("Org.OData.Capabilities.V1.SearchRestrictions", qualifiedName); } [Fact] - public void UnknownAnnotatableTargetReturnsDefaultPropertyValues() + public void InitializSearchRestrictionsTypeWithRecordSuccess() { - // Arrange - SearchRestrictions search = new SearchRestrictions(); - EdmEntityType entityType = new EdmEntityType("NS", "Entity"); + // Assert + EdmModel model = new EdmModel(); + IEdmEnumType searchExpressions = model.FindType("Org.OData.Capabilities.V1.SearchExpressions") as IEdmEnumType; + Assert.NotNull(searchExpressions); - // Act - bool result = search.Load(EdmCoreModel.Instance, entityType); + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Searchable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("UnsupportedExpressions", new EdmEnumMemberExpression( + searchExpressions.Members.First(c => c.Name == "AND"), + searchExpressions.Members.First(c => c.Name == "OR"))) + ); + + // Act + SearchRestrictionsType search = new SearchRestrictionsType(); + search.Initialize(record); // Assert - Assert.False(result); - Assert.True(search.IsSearchable); - Assert.Null(search.Searchable); - Assert.Null(search.UnsupportedExpressions); + Assert.False(search.Searchable); + Assert.NotNull(search.UnsupportedExpressions); + Assert.Equal(SearchExpressions.AND | SearchExpressions.OR, search.UnsupportedExpressions.Value); } [Fact] @@ -59,11 +70,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendar); + SearchRestrictionsType search = model.GetRecord(calendar); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.NotNull(search.UnsupportedExpressions); Assert.Equal(SearchExpressions.phrase, search.UnsupportedExpressions.Value); @@ -92,11 +102,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendars); + SearchRestrictionsType search = model.GetRecord(calendars); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.NotNull(search.UnsupportedExpressions); Assert.Equal(SearchExpressions.group, search.UnsupportedExpressions.Value); @@ -125,11 +134,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendar); + SearchRestrictionsType search = model.GetRecord(calendar); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.Null(search.UnsupportedExpressions); } @@ -154,11 +162,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendars); + SearchRestrictionsType search = model.GetRecord(calendars); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.Null(search.UnsupportedExpressions); } @@ -183,11 +190,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendar); + SearchRestrictionsType search = model.GetRecord(calendar); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.NotNull(search.UnsupportedExpressions); Assert.Equal(SearchExpressions.AND | SearchExpressions.OR, search.UnsupportedExpressions.Value); @@ -213,11 +219,10 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); // Act - SearchRestrictions search = new SearchRestrictions(); - bool result = search.Load(model, calendars); + SearchRestrictionsType search = model.GetRecord(calendars); // Assert - Assert.True(result); + Assert.NotNull(search); Assert.False(search.Searchable); Assert.NotNull(search.UnsupportedExpressions); Assert.Equal(SearchExpressions.AND | SearchExpressions.OR, search.UnsupportedExpressions.Value); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SelectSupportTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SelectSupportTypeTests.cs new file mode 100644 index 0000000..c007edc --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SelectSupportTypeTests.cs @@ -0,0 +1,113 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class SelectSupportTypeTests + { + [Fact] + public void TermAttributeAttachedOnSelectSupportType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.SelectSupport", qualifiedName); + } + + [Fact] + public void InitializSelectSupportTypeWithRecordSuccess() + { + // Assert + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Supported", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("Filterable", new EdmBooleanConstant(true)), + new EdmPropertyConstructor("Expandable", new EdmBooleanConstant(false)), + new EdmPropertyConstructor("Searchable", new EdmBooleanConstant(true)) + // TopSupported + // SkipSupported + // ComputeSupported + // Countable + // Sortable + ); + + // Act + SelectSupportType select = new SelectSupportType(); + select.Initialize(record); + + // Assert + VerifySelectSupportType(select); + } + + [Fact] + public void InitializeSelectSupportTypeTypeWorksWithCsdl() + { + // Arrange + string annotation = @" + + + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + Assert.NotNull(model.EntityContainer); + + // Act + SelectSupportType select = model.GetRecord(model.EntityContainer); + + // Assert + VerifySelectSupportType(select); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + {0} + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + + private static void VerifySelectSupportType(SelectSupportType select) + { + Assert.NotNull(select); + + Assert.Null(select.TopSupported); + Assert.Null(select.SkipSupported); + Assert.Null(select.ComputeSupported); + Assert.Null(select.Countable); + Assert.Null(select.Sortable); + + Assert.True(select.Supported); + Assert.False(select.Expandable); + Assert.True(select.Filterable); + Assert.True(select.Searchable); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SortRestrictionsTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SortRestrictionsTypeTests.cs similarity index 82% rename from test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SortRestrictionsTests.cs rename to test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SortRestrictionsTypeTests.cs index 7bfa0e9..e52711f 100644 --- a/test/Microsoft.OpenAPI.OData.Reader.Tests/Capabilities/SortRestrictionsTests.cs +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/SortRestrictionsTypeTests.cs @@ -6,40 +6,36 @@ using System.Linq; using Microsoft.OData.Edm; using Microsoft.OData.Edm.Csdl; -using Microsoft.OpenApi.OData.Capabilities; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; using Xunit; -namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests { - public class SortRestrictionsTests + public class SortRestrictionsTypeTests { [Fact] - public void KindPropertyReturnsSortRestrictionsEnumMember() + public void TermAttributeAttachedOnSortRestrictionsType() { // Arrange & Act - SortRestrictions sort = new SortRestrictions(); + string qualifiedName = Utils.GetTermQualifiedName(); // Assert - Assert.Equal(CapabilitesTermKind.SortRestrictions, sort.Kind); + Assert.Equal("Org.OData.Capabilities.V1.SortRestrictions", qualifiedName); } [Fact] public void UnknownAnnotatableTargetReturnsDefaultSortRestrictionsValues() { // Arrange & Act - SortRestrictions sort = new SortRestrictions(); EdmEntityType entityType = new EdmEntityType("NS", "Entity"); // Act - bool result = sort.Load(EdmCoreModel.Instance, entityType); + SortRestrictionsType sort = EdmCoreModel.Instance.GetRecord(entityType); // Assert - Assert.False(result); - Assert.True(sort.IsSortable); - Assert.Null(sort.Sortable); - Assert.Null(sort.AscendingOnlyProperties); - Assert.Null(sort.DescendingOnlyProperties); - Assert.Null(sort.NonSortableProperties); + Assert.Null(sort); } [Theory] @@ -60,11 +56,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendar); // guard // Act - SortRestrictions sort = new SortRestrictions(); - bool result = sort.Load(model, calendar); + SortRestrictionsType sort = model.GetRecord(calendar); // Assert - Assert.True(result); VerifySortRestrictions(sort); } @@ -86,11 +80,9 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests Assert.NotNull(calendars); // guard // Act - SortRestrictions sort = new SortRestrictions(); - bool result = sort.Load(model, calendars); + SortRestrictionsType sort = model.GetRecord(calendars); // Assert - Assert.True(result); VerifySortRestrictions(sort); } @@ -129,7 +121,7 @@ namespace Microsoft.OpenApi.OData.Reader.Capabilities.Tests } } - private static void VerifySortRestrictions(SortRestrictions sort) + private static void VerifySortRestrictions(SortRestrictionsType sort) { Assert.NotNull(sort); diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/UpdateRestrictionsTypeTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/UpdateRestrictionsTypeTests.cs new file mode 100644 index 0000000..d9222c8 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Capabilities/UpdateRestrictionsTypeTests.cs @@ -0,0 +1,252 @@ +// ------------------------------------------------------------ +// 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 Microsoft.OData.Edm.Csdl; +using Microsoft.OpenApi.OData.Common; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Capabilities; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Capabilities.Tests +{ + public class UpdateRestrictionsTypeTests + { + [Fact] + public void TermAttributeAttachedOnUpdateRestrictionsType() + { + // Arrange & Act + string qualifiedName = Utils.GetTermQualifiedName(); + + // Assert + Assert.Equal("Org.OData.Capabilities.V1.UpdateRestrictions", qualifiedName); + } + + [Fact] + public void UnknownAnnotatableTargetReturnsDefaultUpdateRestrictionsValues() + { + // Arrange + EdmEntityType entityType = new EdmEntityType("NS", "Entity"); + + // Act + UpdateRestrictionsType update = EdmCoreModel.Instance.GetRecord(entityType); + + // Assert + Assert.Null(update); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntityTypeReturnsCorrectUpdateRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntityType calendar = model.SchemaElements.OfType().First(c => c.Name == "Calendar"); + Assert.NotNull(calendar); // guard + + // Act + UpdateRestrictionsType update = model.GetRecord(calendar); + + // Assert + VerifyUpdateRestrictions(update); + } + + [Theory] + [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] + [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] + public void TargetOnEntitySetReturnsCorrectUpdateRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) + { + // Arrange + const string template = @" + + {0} + "; + + IEdmModel model = GetEdmModel(template, location); + Assert.NotNull(model); // guard + + IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); + Assert.NotNull(calendars); // guard + + // Act + UpdateRestrictionsType update = model.GetRecord(calendars); + + // Assert + VerifyUpdateRestrictions(update); + } + + private static IEdmModel GetEdmModel(string template, EdmVocabularyAnnotationSerializationLocation location) + { + string countAnnotation = @" + + + + + + abc + RelatedEvents + + + + + + + + + + + RequiredScopes1 + RequiredScopes2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + if (location == EdmVocabularyAnnotationSerializationLocation.OutOfLine) + { + countAnnotation = string.Format(template, countAnnotation); + return CapabilitiesModelHelper.GetEdmModelOutline(countAnnotation); + } + else + { + return CapabilitiesModelHelper.GetEdmModelTypeInline(countAnnotation); + } + } + + private static void VerifyUpdateRestrictions(UpdateRestrictionsType update) + { + Assert.NotNull(update); + + Assert.NotNull(update.Updatable); + Assert.False(update.Updatable.Value); + + Assert.NotNull(update.NonUpdatableNavigationProperties); + Assert.Equal(2, update.NonUpdatableNavigationProperties.Count); + Assert.Equal("abc|RelatedEvents", String.Join("|", update.NonUpdatableNavigationProperties)); + + Assert.True(update.IsNonUpdatableNavigationProperty("abc")); + Assert.True(update.IsNonUpdatableNavigationProperty("RelatedEvents")); + Assert.False(update.IsNonUpdatableNavigationProperty("Others")); + + // MaxLevels + Assert.NotNull(update.MaxLevels); + Assert.Equal(8, update.MaxLevels); + + // QueryOptions + Assert.NotNull(update.QueryOptions); + Assert.True(update.QueryOptions.ComputeSupported); + Assert.False(update.QueryOptions.SortSupported); + + // CustomHeaders + Assert.NotNull(update.CustomHeaders); + Assert.Equal(2, update.CustomHeaders.Count); + + // CustomQueryOptions + Assert.NotNull(update.CustomQueryOptions); + Assert.Equal(2, update.CustomQueryOptions.Count); + } + } +} diff --git a/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Core/PrimitiveExampleValueTests.cs b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Core/PrimitiveExampleValueTests.cs new file mode 100644 index 0000000..12b98e8 --- /dev/null +++ b/test/Microsoft.OpenAPI.OData.Reader.Tests/Vocabulary/Core/PrimitiveExampleValueTests.cs @@ -0,0 +1,138 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Microsoft.OData.Edm; +using Microsoft.OData.Edm.Csdl; +using Microsoft.OData.Edm.Vocabularies; +using Microsoft.OpenApi.OData.Edm; +using Microsoft.OpenApi.OData.Vocabulary.Core; +using Xunit; + +namespace Microsoft.OpenApi.OData.Reader.Vocabulary.Core.Tests +{ + public class PrimitiveExampleValueTests + { + [Fact] + public void DefaultPropertyAsNull() + { + // Arrange + PrimitiveExampleValue value = new PrimitiveExampleValue(); + + // Act & Assert + Assert.Null(value.Description); + Assert.Null(value.Value); + } + + [Fact] + public void InitializeWithNullRecordThrows() + { + // Arrange & Act + PrimitiveExampleValue value = new PrimitiveExampleValue(); + + // Assert + Assert.Throws("record", () => value.Initialize(record: null)); + } + + [Fact] + public void InitializeWithPrimitiveValueRecordSuccess() + { + // Arrange + IEdmRecordExpression record = new EdmRecordExpression( + new EdmPropertyConstructor("Description", new EdmStringConstant("HelloWorld!")), + new EdmPropertyConstructor("Value", new EdmBooleanConstant(true))); + PrimitiveExampleValue value = new PrimitiveExampleValue(); + Assert.Null(value.Description); + Assert.Null(value.Value); + + // Act + value.Initialize(record); + + // Assert + Assert.NotNull(value.Description); + Assert.Equal("HelloWorld!", value.Description); + Assert.NotNull(value.Value); + + Assert.NotNull(value.Value.Value); + Assert.Equal(true, value.Value.Value); + } + + public static IEnumerable PrimitiveData => + new List + { + new object[] { @"String=""Hello World""", "Hello World" }, + new object[] { @"Int=""42""", (long)42 }, + new object[] { @"Bool=""true""", true }, + new object[] { @"Bool=""false""", false }, + new object[] { @"TimeOfDay=""15:38:25.1090000""", new TimeOfDay(15, 38, 25, 109) }, + new object[] { @"Date=""2014-10-13""", new Date(2014, 10, 13) }, + new object[] { @"Duration=""PT0S""", new TimeSpan() }, + // new object[] { @"Binary=""AQ==""", new byte[] { 1 }, }, has problem in ODL? + new object[] { @"Float=""3.14""", 3.14 }, + new object[] { @"Decimal=""3.14""", 3.14m }, + new object[] { @"DateTimeOffset=""0001-01-01T00:00:00Z""", new DateTimeOffset() }, + new object[] { @"Guid=""21EC2020-3AEA-1069-A2DD-08002B30309D""", new Guid("21EC2020-3AEA-1069-A2DD-08002B30309D") }, + }; + + [Theory] + [MemberData(nameof(PrimitiveData))] + public void PrimitiveExamplevalueInitializeWorksForPrimitiveData(string data, object except) + { + // Arrange + string annotation = $@" + + + + + "; + + IEdmModel model = GetEdmModel(annotation); + Assert.NotNull(model); // guard + + IEdmEntityType customer = model.SchemaElements.OfType().First(c => c.Name == "Customer"); + Assert.NotNull(customer); // guard + IEdmProperty dataProperty = customer.FindProperty("Data"); + Assert.NotNull(dataProperty); + + // Act + PrimitiveExampleValue value = model.GetRecord(dataProperty, "Org.OData.Core.V1.Example"); + + // Assert + Assert.NotNull(value); + Assert.Equal("Primitive example value", value.Description); + Assert.NotNull(value.Value); + Assert.Equal(except, value.Value.Value); + } + + private IEdmModel GetEdmModel(string annotation) + { + const string template = @" + + + + + + + + + {0} + + + + +"; + string modelText = string.Format(template, annotation); + + IEdmModel model; + + bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out _); + Assert.True(result); + return model; + } + } +}