/// <summary> /// Create key parameters for the <see cref="ODataKeySegment"/>. /// </summary> /// <param name="context">The OData context.</param> /// <param name="keySegment">The key segment.</param> /// <param name="parameterNameMapping">The parameter name mapping.</param> /// <returns>The created the list of <see cref="OpenApiParameter"/>.</returns> public static IList <OpenApiParameter> CreateKeyParameters(this ODataContext context, ODataKeySegment keySegment, IDictionary <string, string> parameterNameMapping = null) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(keySegment, nameof(keySegment)); IList <OpenApiParameter> parameters = new List <OpenApiParameter>(); IEdmEntityType entityType = keySegment.EntityType; IList <IEdmStructuralProperty> keys = entityType.Key().ToList(); if (keys.Count() == 1) { string keyName = keys.First().Name; // If dictionary parameterNameMapping is defined, there's no need of setting the // keyName, we will retrieve this from the dictionary key. if (context.Settings.PrefixEntityTypeNameBeforeKey && parameterNameMapping == null) { keyName = entityType.Name + "-" + keys.First().Name; } OpenApiParameter parameter = new OpenApiParameter { Name = parameterNameMapping == null ? keyName: parameterNameMapping[keyName], In = ParameterLocation.Path, Required = true, Description = "key: " + keyName + " of " + entityType.Name, Schema = context.CreateEdmTypeSchema(keys.First().Type) }; parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name)); parameters.Add(parameter); } else { // append key parameter foreach (var keyProperty in entityType.Key()) { OpenApiParameter parameter = new OpenApiParameter { Name = parameterNameMapping == null ? keyProperty.Name: parameterNameMapping[keyProperty.Name],// By design: not prefix with type name if enable type name prefix In = ParameterLocation.Path, Required = true, Description = "key: " + keyProperty.Name + " of " + entityType.Name, Schema = context.CreateEdmTypeSchema(keyProperty.Type) }; parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name)); parameters.Add(parameter); } } return(parameters); }
/// <summary> /// Create key parameters for the <see cref="ODataKeySegment"/>. /// </summary> /// <param name="keySegment">The key segment.</param> /// <returns>The created the list of <see cref="OpenApiParameter"/>.</returns> public static IList <OpenApiParameter> CreateKeyParameters(this ODataContext context, ODataKeySegment keySegment) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(keySegment, nameof(keySegment)); IList <OpenApiParameter> parameters = new List <OpenApiParameter>(); IEdmEntityType entityType = keySegment.EntityType; IList <IEdmStructuralProperty> keys = entityType.Key().ToList(); if (keys.Count() == 1) { string keyName = keys.First().Name + keySegment.KeyIndex.ToString(); if (context.Settings.PrefixEntityTypeNameBeforeKey) { keyName = entityType.Name + "-" + keyName; } OpenApiParameter parameter = new OpenApiParameter { Name = keyName, In = ParameterLocation.Path, Required = true, Description = "key: " + keyName, Schema = context.CreateEdmTypeSchema(keys.First().Type) }; parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name)); parameters.Add(parameter); } else { // append key parameter foreach (var keyProperty in entityType.Key()) { string keyName = keyProperty.Name + keySegment.KeyIndex.ToString(); OpenApiParameter parameter = new OpenApiParameter { Name = keyName, In = ParameterLocation.Path, Required = true, Description = "key: " + keyName, Schema = context.CreateEdmTypeSchema(keyProperty.Type) }; parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name)); parameters.Add(parameter); } } return(parameters); }
/// <summary> /// Create the <see cref="OpenApiResponses"/> for a <see cref="IEdmOperation"/> /// </summary> /// <param name="context">The OData context.</param> /// <param name="operation">The Edm operation.</param> /// <returns>The created <see cref="OpenApiResponses"/>.</returns> public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(operation, nameof(operation)); OpenApiResponses responses = new OpenApiResponses(); if (operation.ReturnType != null) { if (operation.IsAction()) { //responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse()); OpenApiResponse response = new OpenApiResponse { Description = "Success", Content = new Dictionary <string, OpenApiMediaType> { { Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = context.CreateEdmTypeSchema(operation.ReturnType) } } } }; responses.Add(Constants.StatusCode200, response); } else { OpenApiResponse response = new OpenApiResponse { Description = "Success", Content = new Dictionary <string, OpenApiMediaType> { { Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = context.CreateEdmTypeSchema(operation.ReturnType) } } } }; responses.Add(Constants.StatusCode200, response); } } // both action & function has the default response. responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse()); return(responses); }
public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionComplexType() { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmComplexType complex = model.SchemaElements.OfType <IEdmComplexType>().First(c => c.Name == "AirportLocation"); ODataContext context = new ODataContext(model); IEdmCollectionTypeReference collectionType = new EdmCollectionTypeReference( new EdmCollectionType(new EdmComplexTypeReference(complex, true))); // Act var schema = context.CreateEdmTypeSchema(collectionType); Assert.NotNull(schema); string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // & Assert Assert.Equal(@"{ ""type"": ""array"", ""items"": { ""anyOf"": [ { ""$ref"": ""#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation"" } ], ""nullable"": true } }".ChangeLineBreaks(), json); }
public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmEntityType entity = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Manager"); Assert.NotNull(entity); // guard IEdmEntityTypeReference entityTypeReference = new EdmEntityTypeReference(entity, isNullable); ODataContext context = new ODataContext(model); // Act var schema = context.CreateEdmTypeSchema(entityTypeReference); // & Assert Assert.NotNull(schema); if (isNullable) { Assert.Null(schema.Reference); Assert.NotNull(schema.AnyOf); Assert.NotEmpty(schema.AnyOf); var anyOf = Assert.Single(schema.AnyOf); Assert.NotNull(anyOf.Reference); Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type); Assert.Equal(entity.FullTypeName(), anyOf.Reference.Id); } else { Assert.Null(schema.AnyOf); Assert.NotNull(schema.Reference); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(entity.FullTypeName(), schema.Reference.Id); } }
public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionPrimitiveType() { // Arrange IEdmModel model = EdmCoreModel.Instance; ODataContext context = new ODataContext(model); IEdmCollectionTypeReference collectionType = new EdmCollectionTypeReference( new EdmCollectionType(EdmCoreModel.Instance.GetInt32(true))); // Act var schema = context.CreateEdmTypeSchema(collectionType); Assert.NotNull(schema); string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // & Assert Assert.Equal(@"{ ""type"": ""array"", ""items"": { ""maximum"": 2147483647, ""minimum"": -2147483648, ""type"": ""integer"", ""format"": ""int32"", ""nullable"": true } }".ChangeLineBreaks(), json); }
public void CreateEdmTypeSchemaReturnSchemaForInt32(bool isNullable) { // Arrange IEdmModel model = EdmCoreModel.Instance; ODataContext context = new ODataContext(model); IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetInt32(isNullable); // Act var schema = context.CreateEdmTypeSchema(edmTypeReference); Assert.NotNull(schema); // guard string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // & Assert if (isNullable) { Assert.Equal(@"{ ""maximum"": 2147483647, ""minimum"": -2147483648, ""type"": ""integer"", ""format"": ""int32"", ""nullable"": true }".ChangeLineBreaks(), json); } else { Assert.Equal(@"{ ""maximum"": 2147483647, ""minimum"": -2147483648, ""type"": ""integer"", ""format"": ""int32"" }".ChangeLineBreaks(), json); } }
/// <summary> /// Create a map of string/<see cref="OpenApiSchema"/> map for a <see cref="IEdmStructuredType"/>'s all properties. /// </summary> /// <param name="context">The OData context.</param> /// <param name="structuredType">The Edm structured type.</param> /// <returns>The created map of <see cref="OpenApiSchema"/>.</returns> public static IDictionary <string, OpenApiSchema> CreateStructuredTypePropertiesSchema(this ODataContext context, IEdmStructuredType structuredType) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(structuredType, nameof(structuredType)); // The name is the property name, the value is a Schema Object describing the allowed values of the property. IDictionary <string, OpenApiSchema> properties = new Dictionary <string, OpenApiSchema>(); // structure properties foreach (var property in structuredType.DeclaredStructuralProperties()) { OpenApiSchema propertySchema = context.CreatePropertySchema(property); propertySchema.Description = context.Model.GetDescriptionAnnotation(property); propertySchema.Extensions.AddCustomAtributesToExtensions(context, property); properties.Add(property.Name, propertySchema); } // navigation properties foreach (var property in structuredType.DeclaredNavigationProperties()) { OpenApiSchema propertySchema = context.CreateEdmTypeSchema(property.Type); propertySchema.Description = context.Model.GetDescriptionAnnotation(property); propertySchema.Extensions.AddCustomAtributesToExtensions(context, property); properties.Add(property.Name, propertySchema); } return(properties); }
public void CreateEdmTypeSchemaReturnSchemaForInt64(bool isNullable, bool IEEE754Compatible) { // Arrange IEdmModel model = EdmCoreModel.Instance; OpenApiConvertSettings settings = new OpenApiConvertSettings { IEEE754Compatible = IEEE754Compatible }; ODataContext context = new ODataContext(model, settings); IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetInt64(isNullable); // Act var schema = context.CreateEdmTypeSchema(edmTypeReference); Assert.NotNull(schema); // guard // & Assert if (IEEE754Compatible) { Assert.Null(schema.Type); Assert.NotNull(schema.AnyOf); Assert.Equal(2, schema.AnyOf.Count); Assert.Equal(new[] { "integer", "string" }, schema.AnyOf.Select(a => a.Type)); } else { Assert.Equal("integer", schema.Type); Assert.Null(schema.AnyOf); } Assert.Equal(isNullable, schema.Nullable); }
/// <summary> /// Create a map of string/<see cref="OpenApiSchema"/> map for a <see cref="IEdmStructuredType"/>'s all properties. /// </summary> /// <param name="context">The OData context.</param> /// <param name="structuredType">The Edm structured type.</param> /// <returns>The created map of <see cref="OpenApiSchema"/>.</returns> public static IDictionary <string, OpenApiSchema> CreateStructuredTypeCombinedPropertiesSchema(this ODataContext context, IEdmStructuredType structuredType) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(structuredType, nameof(structuredType)); // The name is the property name, the value is a Schema Object describing the allowed values of the property. IDictionary <string, OpenApiSchema> properties = new Dictionary <string, OpenApiSchema>(); // structure properties foreach (var property in structuredType.StructuralProperties()) { // OpenApiSchema propertySchema = property.Type.CreateSchema(); // propertySchema.Default = property.DefaultValueString != null ? new OpenApiString(property.DefaultValueString) : null; if (property.Type.FullName() != structuredType.FullTypeName() && property.Type.FullName() != $"Collection({structuredType.FullTypeName()})") { properties.Add(property.Name, context.CreatePropertySchema(property)); } } // navigation properties foreach (var property in structuredType.NavigationProperties()) { if (property.Type.FullName() != structuredType.FullTypeName() && property.Type.FullName() != $"Collection({structuredType.FullTypeName()})") { OpenApiSchema propertySchema = context.CreateEdmTypeSchema(property.Type); properties.Add(property.Name, propertySchema); } } return(properties); }
public void CreateEdmTypeSchemaReturnSchemaForGuid(bool isNullable) { // Arrange IEdmModel model = EdmCoreModel.Instance; ODataContext context = new ODataContext(model); IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetGuid(isNullable); // Act var schema = context.CreateEdmTypeSchema(edmTypeReference); Assert.NotNull(schema); // guard string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // & Assert if (isNullable) { Assert.Equal(@"{ ""pattern"": ""^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"", ""type"": ""string"", ""format"": ""uuid"", ""nullable"": true }".ChangeLineBreaks(), json); } else { Assert.Equal(@"{ ""pattern"": ""^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"", ""type"": ""string"", ""format"": ""uuid"" }".ChangeLineBreaks(), json); } }
public void CreateEdmTypeSchemaThrowArgumentNullEdmTypeReference() { // Arrange ODataContext context = new ODataContext(EdmCoreModel.Instance); // Act & Assert Assert.Throws <ArgumentNullException>("edmTypeReference", () => context.CreateEdmTypeSchema(edmTypeReference: null)); }
public void CreateEdmTypeSchemaThrowArgumentNullContext() { // Arrange ODataContext context = null; // Act & Assert Assert.Throws <ArgumentNullException>("context", () => context.CreateEdmTypeSchema(edmTypeReference: null)); }
public void CreateEdmTypeSchemaReturnSchemaForEnumType(bool isNullable, OpenApiSpecVersion specVersion) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmEnumType enumType = model.SchemaElements.OfType <IEdmEnumType>().First(c => c.Name == "PersonGender"); Assert.NotNull(enumType); // guard IEdmEnumTypeReference enumTypeReference = new EdmEnumTypeReference(enumType, isNullable); ODataContext context = new ODataContext(model); context.Settings.OpenApiSpecVersion = specVersion; // Act var schema = context.CreateEdmTypeSchema(enumTypeReference); // & Assert Assert.NotNull(schema); if (specVersion == OpenApiSpecVersion.OpenApi2_0) { Assert.NotNull(schema.Reference); Assert.Null(schema.AnyOf); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(enumType.FullTypeName(), schema.Reference.Id); Assert.Equal(isNullable, schema.Nullable); } else { if (isNullable) { Assert.NotNull(schema.AnyOf); Assert.NotEmpty(schema.AnyOf); Assert.Null(schema.Reference); Assert.Equal(2, schema.AnyOf.Count); var anyOfRef = schema.AnyOf.FirstOrDefault(); Assert.NotNull(anyOfRef.Reference); Assert.Equal(ReferenceType.Schema, anyOfRef.Reference.Type); Assert.Equal(enumType.FullTypeName(), anyOfRef.Reference.Id); var anyOfNull = schema.AnyOf.Skip(1).FirstOrDefault(); Assert.NotNull(anyOfNull.Type); Assert.Equal("object", anyOfNull.Type); Assert.True(anyOfNull.Nullable); } else { Assert.Null(schema.AnyOf); Assert.NotNull(schema.Reference); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(enumType.FullTypeName(), schema.Reference.Id); } } }
/// <summary> /// Create the list of <see cref="OpenApiParameter"/> for a <see cref="IEdmFunction"/>. /// </summary> /// <param name="context">The OData context.</param> /// <param name="function">The Edm function.</param> /// <param name="parameterNameMapping">The parameter name mapping.</param> /// <returns>The created list of <see cref="OpenApiParameter"/>.</returns> public static IList <OpenApiParameter> CreateParameters(this ODataContext context, IEdmFunction function, IDictionary <string, string> parameterNameMapping = null) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(function, nameof(function)); IList <OpenApiParameter> parameters = new List <OpenApiParameter>(); int skip = function.IsBound ? 1 : 0; foreach (IEdmOperationParameter edmParameter in function.Parameters.Skip(skip)) { // Structured or collection-valued parameters are represented as a parameter alias // in the path template and the parameters array contains a Parameter Object for // the parameter alias as a query option of type string. if (edmParameter.Type.IsStructured() || edmParameter.Type.IsCollection()) { parameters.Add(new OpenApiParameter { Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name], In = ParameterLocation.Query, // as query option Required = true, Schema = new OpenApiSchema { Type = "string", // These Parameter Objects optionally can contain the field description, // whose value is the value of the unqualified annotation Core.Description of the parameter. Description = context.Model.GetDescriptionAnnotation(edmParameter) }, // The parameter description describes the format this URL-encoded JSON object or array, and/or reference to [OData-URL]. Description = "The URL-encoded JSON " + (edmParameter.Type.IsStructured() ? "array" : "object") }); } else { // Primitive parameters use the same type mapping as described for primitive properties. parameters.Add(new OpenApiParameter { Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name], In = ParameterLocation.Path, Required = true, Schema = context.CreateEdmTypeSchema(edmParameter.Type) }); } } return(parameters); }
/// <summary> /// Create a <see cref="OpenApiRequestBody"/> for a <see cref="IEdmAction"/>. /// </summary> /// <param name="context">The OData context.</param> /// <param name="action">The Edm action.</param> /// <returns>The created <see cref="OpenApiRequestBody"/> or null.</returns> public static OpenApiRequestBody CreateRequestBody(this ODataContext context, IEdmAction action) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(action, nameof(action)); // return null for empty action parameters int skip = 0; if (action.IsBound) { if (action.Parameters.Count() <= 1) { return(null); } skip = 1; //skip the binding parameter } else { if (!action.Parameters.Any()) { return(null); } } OpenApiSchema parametersSchema = new OpenApiSchema { Type = "object", Properties = new Dictionary <string, OpenApiSchema>() }; foreach (var parameter in action.Parameters.Skip(skip)) { parametersSchema.Properties.Add(parameter.Name, context.CreateEdmTypeSchema(parameter.Type)); } OpenApiRequestBody requestBody = new OpenApiRequestBody { Description = "Action parameters", Required = true, Content = new Dictionary <string, OpenApiMediaType>() }; requestBody.Content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = parametersSchema }); return(requestBody); }
/// <summary> /// Create a <see cref="OpenApiSchema"/> for a <see cref="IEdmTypeReference"/>. /// </summary> /// <param name="context">The OData context.</param> /// <param name="edmTypeReference">The Edm type reference.</param> /// <returns>The created <see cref="OpenApiSchema"/>.</returns> public static OpenApiSchema CreateEdmTypeSchema(this ODataContext context, IEdmTypeReference edmTypeReference) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(edmTypeReference, nameof(edmTypeReference)); switch (edmTypeReference.TypeKind()) { case EdmTypeKind.Collection: // Collection-valued structural and navigation are represented as Schema Objects of type array. // The value of the items keyword is a Schema Object specifying the type of the items. return(new OpenApiSchema { Type = "array", Items = context.CreateEdmTypeSchema(edmTypeReference.AsCollection().ElementType()) }); // Complex, enum, entity, entity reference are represented as JSON References to the Schema Object of the complex, // enum, entity and entity reference type, either as local references for types directly defined in the CSDL document, // or as external references for types defined in referenced CSDL documents. case EdmTypeKind.Complex: case EdmTypeKind.Entity: return(context.CreateStructuredTypeSchema(edmTypeReference.AsStructured())); case EdmTypeKind.Enum: return(context.CreateEnumTypeSchema(edmTypeReference.AsEnum())); // Primitive properties of type Edm.PrimitiveType, Edm.Stream, and any of the Edm.Geo* types are // represented as Schema Objects that are JSON References to definitions in the Definitions Object case EdmTypeKind.Primitive: IEdmPrimitiveTypeReference primitiveTypeReference = (IEdmPrimitiveTypeReference)edmTypeReference; return(context.CreateSchema(primitiveTypeReference)); case EdmTypeKind.TypeDefinition: return(context.CreateSchema(((IEdmTypeDefinitionReference)edmTypeReference).TypeDefinition().UnderlyingType)); case EdmTypeKind.EntityReference: return(context.CreateTypeDefinitionSchema(edmTypeReference.AsTypeDefinition())); case EdmTypeKind.None: default: throw Error.NotSupported(String.Format(SRResource.NotSupportedEdmTypeKind, edmTypeReference.TypeKind())); } }
/// <summary> /// Create a <see cref="OpenApiSchema"/> for a <see cref="IEdmProperty"/>. /// Each structural property and navigation property is represented as a name/value pair of the /// standard OpenAPI properties object. The name is the property name, /// the value is a Schema Object describing the allowed values of the property. /// </summary> /// <param name="context">The OData context.</param> /// <param name="property">The Edm property.</param> /// <returns>The created <see cref="OpenApiSchema"/>.</returns> public static OpenApiSchema CreatePropertySchema(this ODataContext context, IEdmProperty property) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(property, nameof(property)); OpenApiSchema schema = context.CreateEdmTypeSchema(property.Type); switch (property.PropertyKind) { case EdmPropertyKind.Structural: IEdmStructuralProperty structuralProperty = (IEdmStructuralProperty)property; schema.Default = CreateDefault(structuralProperty); break; } // The Schema Object for a property optionally can contain the field description, // whose value is the value of the unqualified annotation Core.Description of the property. schema.Description = context.Model.GetDescriptionAnnotation(property); return(schema); }
public void CreateEdmTypeSchemaReturnSchemaForEnumType(bool isNullable, OpenApiSpecVersion specVersion) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmEnumType enumType = model.SchemaElements.OfType <IEdmEnumType>().First(c => c.Name == "PersonGender"); Assert.NotNull(enumType); // guard IEdmEnumTypeReference enumTypeReference = new EdmEnumTypeReference(enumType, isNullable); ODataContext context = new ODataContext(model); context.Settings.OpenApiSpecVersion = specVersion; // Act var schema = context.CreateEdmTypeSchema(enumTypeReference); // & Assert Assert.NotNull(schema); // Although the schema will be set // for openApiV2 nullable will not be serialized Assert.Equal(isNullable, schema.Nullable); if (specVersion == OpenApiSpecVersion.OpenApi2_0) { Assert.NotNull(schema.Reference); Assert.Null(schema.AnyOf); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(enumType.FullTypeName(), schema.Reference.Id); } else { Assert.Null(schema.Reference); Assert.NotNull(schema.AnyOf); Assert.NotEmpty(schema.AnyOf); var anyOf = Assert.Single(schema.AnyOf); Assert.NotNull(anyOf.Reference); Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type); Assert.Equal(enumType.FullTypeName(), anyOf.Reference.Id); } }
public void CreateEdmTypeSchemaReturnSchemaForNonNullableCollectionPrimitiveType() { // Arrange IEdmModel model = EdmCoreModel.Instance; ODataContext context = new ODataContext(model); IEdmCollectionTypeReference collectionType = new EdmCollectionTypeReference( new EdmCollectionType(EdmCoreModel.Instance.GetString(false))); // Act var schema = context.CreateEdmTypeSchema(collectionType); Assert.NotNull(schema); string json = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // & Assert Assert.Equal(@"{ ""type"": ""array"", ""items"": { ""type"": ""string"" } }".ChangeLineBreaks(), json); }
public void CreateEdmTypeSchemaReturnSchemaForSingle(bool isNullable) { // Arrange IEdmModel model = EdmCoreModel.Instance; ODataContext context = new ODataContext(model); IEdmTypeReference edmTypeReference = EdmCoreModel.Instance.GetSingle(isNullable); // Act var schema = context.CreateEdmTypeSchema(edmTypeReference); Assert.NotNull(schema); // guard // & Assert Assert.Null(schema.Type); Assert.Equal("float", schema.Format); Assert.Equal(isNullable, schema.Nullable); Assert.Null(schema.OneOf); Assert.NotNull(schema.AnyOf); Assert.Equal(3, schema.AnyOf.Count); }
public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenApiSpecVersion specVersion) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmComplexType complex = model.SchemaElements.OfType <IEdmComplexType>().First(c => c.Name == "AirportLocation"); Assert.NotNull(complex); // guard IEdmComplexTypeReference complexTypeReference = new EdmComplexTypeReference(complex, isNullable); ODataContext context = new ODataContext(model); context.Settings.OpenApiSpecVersion = specVersion; // Act var schema = context.CreateEdmTypeSchema(complexTypeReference); // & Assert Assert.NotNull(schema); if (specVersion == OpenApiSpecVersion.OpenApi2_0 || isNullable == false) { Assert.Null(schema.AnyOf); Assert.NotNull(schema.Reference); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(complex.FullTypeName(), schema.Reference.Id); } else { Assert.Null(schema.Reference); Assert.NotNull(schema.AnyOf); Assert.NotEmpty(schema.AnyOf); Assert.Equal(2, schema.AnyOf.Count); var anyOf = schema.AnyOf.FirstOrDefault(); Assert.NotNull(anyOf.Reference); Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type); Assert.Equal(complex.FullTypeName(), anyOf.Reference.Id); } }
/// <summary> /// Create the list of <see cref="OpenApiParameter"/> for a <see cref="IEdmFunction"/>. /// </summary> /// <param name="context">The OData context.</param> /// <param name="function">The Edm function.</param> /// <param name="parameterNameMapping">The parameter name mapping.</param> /// <returns>The created list of <see cref="OpenApiParameter"/>.</returns> public static IList <OpenApiParameter> CreateParameters(this ODataContext context, IEdmFunction function, IDictionary <string, string> parameterNameMapping = null) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(function, nameof(function)); IList <OpenApiParameter> parameters = new List <OpenApiParameter>(); int skip = function.IsBound ? 1 : 0; foreach (IEdmOperationParameter edmParameter in function.Parameters.Skip(skip)) { if (parameterNameMapping != null) { if (!parameterNameMapping.ContainsKey(edmParameter.Name)) { continue; } } OpenApiParameter parameter; if (edmParameter.Type.IsStructured() || edmParameter.Type.IsCollection()) { parameter = new OpenApiParameter { Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name], In = ParameterLocation.Path, Required = true, // Create schema in the Content property to indicate that the parameters are serialized as JSON Content = new Dictionary <string, OpenApiMediaType> { { Constants.ApplicationJsonMediaType, new OpenApiMediaType { Schema = new OpenApiSchema { Type = "array", Items = new OpenApiSchema { Type = "string" }, // These Parameter Objects optionally can contain the field description, // whose value is the value of the unqualified annotation Core.Description of the parameter. Description = context.Model.GetDescriptionAnnotation(edmParameter) } } } }, // The parameter description describes the format this URL-encoded JSON object or array, and/or reference to [OData-URL]. Description = "The URL-encoded JSON " + (edmParameter.Type.IsStructured() ? "array" : "object") }; } else { // Primitive parameters use the same type mapping as described for primitive properties. bool isOptionalParameter = edmParameter is IEdmOptionalParameter; parameter = new OpenApiParameter { Name = parameterNameMapping == null ? edmParameter.Name : parameterNameMapping[edmParameter.Name], In = isOptionalParameter ? ParameterLocation.Query : ParameterLocation.Path, Required = !isOptionalParameter, Schema = context.CreateEdmTypeSchema(edmParameter.Type) }; } if (parameterNameMapping != null) { var quote = edmParameter.Type.Definition.ShouldPathParameterBeQuoted(context.Settings) ? "'" : string.Empty; parameter.Description = $"Usage: {edmParameter.Name}={quote}{{{parameterNameMapping[edmParameter.Name]}}}{quote}"; } parameters.Add(parameter); } return(parameters); }
/// <summary> /// Create the <see cref="OpenApiResponses"/> for a <see cref="IEdmOperation"/> /// </summary> /// <param name="context">The OData context.</param> /// <param name="operation">The Edm operation.</param> /// <param name="path">The OData path.</param> /// <returns>The created <see cref="OpenApiResponses"/>.</returns> public static OpenApiResponses CreateResponses(this ODataContext context, IEdmOperation operation, ODataPath path) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(operation, nameof(operation)); Utils.CheckArgumentNull(path, nameof(path)); OpenApiResponses responses = new(); if (operation.IsAction() && operation.ReturnType == null) { responses.Add(Constants.StatusCode204, Constants.StatusCode204.GetResponse()); } else { OpenApiSchema schema; if (operation.ReturnType.IsCollection()) { // Get the entity type of the previous segment IEdmEntityType entityType = path.Segments.Reverse().Skip(1)?.Take(1)?.FirstOrDefault()?.EntityType; schema = new OpenApiSchema { Title = entityType == null ? null : $"Collection of {entityType.Name}", Type = "object", Properties = new Dictionary <string, OpenApiSchema> { { "value", context.CreateEdmTypeSchema(operation.ReturnType) } } }; } else if (operation.ReturnType.IsPrimitive()) { // A property or operation response that is of a primitive type is represented as an object with a single name/value pair, // whose name is value and whose value is a primitive value. schema = new OpenApiSchema { Type = "object", Properties = new Dictionary <string, OpenApiSchema> { { "value", context.CreateEdmTypeSchema(operation.ReturnType) } } }; } else { schema = context.CreateEdmTypeSchema(operation.ReturnType); } string mediaType = Constants.ApplicationJsonMediaType; if (operation.ReturnType.AsPrimitive()?.PrimitiveKind() == EdmPrimitiveTypeKind.Stream) { // Responses of types Edm.Stream should be application/octet-stream mediaType = Constants.ApplicationOctetStreamMediaType; } OpenApiResponse response = new() { Description = "Success", Content = new Dictionary <string, OpenApiMediaType> { { mediaType, new OpenApiMediaType { Schema = schema } } } }; responses.Add(context.Settings.UseSuccessStatusCodeRange ? Constants.StatusCodeClass2XX : Constants.StatusCode200, response); } if (context.Settings.ErrorResponsesAsDefault) { responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse()); } else { responses.Add(Constants.StatusCodeClass4XX, Constants.StatusCodeClass4XX.GetResponse()); responses.Add(Constants.StatusCodeClass5XX, Constants.StatusCodeClass5XX.GetResponse()); } return(responses); }