/// <summary> /// Create the collection of <see cref="OpenApiLink"/> object. /// </summary> /// <param name="context">The OData context.</param> /// <param name="entitySet">The Entity Set.</param> /// <returns>The created dictionary of <see cref="OpenApiLink"/> object.</returns> public static IDictionary <string, OpenApiLink> CreateLinks(this ODataContext context, IEdmEntitySet entitySet) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(entitySet, nameof(entitySet)); IDictionary <string, OpenApiLink> links = new Dictionary <string, OpenApiLink>(); IEdmEntityType entityType = entitySet.EntityType(); foreach (var np in entityType.DeclaredNavigationProperties()) { OpenApiLink link = new OpenApiLink(); string typeName = entitySet.EntityType().Name; link.OperationId = entitySet.Name + "." + typeName + ".Get" + Utils.UpperFirstChar(typeName); link.Parameters = new Dictionary <string, RuntimeExpressionAnyWrapper>(); foreach (var key in entityType.Key()) { link.Parameters[key.Name] = new RuntimeExpressionAnyWrapper { Any = new OpenApiString("$request.path." + key.Name) }; } links[np.Name] = link; } return(links); }
public void CreateCollectionNavigationPropertyPathItemReturnsCorrectPathItem(bool containment, bool keySegment, OperationType[] expected) { // Arrange IEdmModel model = GetEdmModel(""); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() .FirstOrDefault(c => c.ContainsTarget == containment && c.TargetMultiplicity() == EdmMultiplicity.Many); Assert.NotNull(property); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property)); if (keySegment) { path.Push(new ODataKeySegment(property.ToEntityType())); } // 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(o => o.Key)); }
/// <summary> /// Create the collection of <see cref="OpenApiLink"/> object. /// </summary> /// <param name="context">The OData context.</param> /// <param name="entityType">The Entity type.</param> /// <param name ="sourceElementName">The name of the source of the <see cref="IEdmEntityType" />.</param> /// <returns>The created dictionary of <see cref="OpenApiLink"/> object.</returns> public static IDictionary <string, OpenApiLink> CreateLinks(this ODataContext context, IEdmEntityType entityType, string sourceElementName) { Utils.CheckArgumentNull(context, nameof(context)); Utils.CheckArgumentNull(entityType, nameof(entityType)); Utils.CheckArgumentNullOrEmpty(sourceElementName, nameof(sourceElementName)); IDictionary <string, OpenApiLink> links = new Dictionary <string, OpenApiLink>(); foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) { OpenApiLink link = new OpenApiLink { OperationId = sourceElementName + "." + entityType.Name + ".Get" + Utils.UpperFirstChar(entityType.Name), Parameters = new Dictionary <string, RuntimeExpressionAnyWrapper>() }; foreach (IEdmStructuralProperty key in entityType.Key()) { link.Parameters[key.Name] = new RuntimeExpressionAnyWrapper { Any = new OpenApiString("$request.path." + key.Name) }; } links[np.Name] = link; } return(links); }
public void EntityType_reference_extensions() { IEdmModel edmModel = this.GetEdmModel(); IEdmEntityType derivedEntityType = edmModel.SchemaElements.OfType <IEdmEntityType>().First(c => c.BaseType != null); IEdmEntityType baseEntityType = derivedEntityType.BaseEntityType(); Assert.IsNotNull(baseEntityType, "Base entity type should not be null!"); IEdmEntityTypeReference derivedEntityTypeRef = (IEdmEntityTypeReference)derivedEntityType.ToTypeReference(); Assert.AreEqual(baseEntityType, derivedEntityTypeRef.BaseEntityType(), "EntityTypeReference.BaseEntityType()"); Assert.AreEqual(baseEntityType, derivedEntityTypeRef.BaseType(), "EntityTypeReference.BaseType()"); Assert.AreEqual(derivedEntityType.IsAbstract, derivedEntityTypeRef.IsAbstract(), "StructuralTypeReference.IsAbstract()"); Assert.AreEqual(derivedEntityType.IsOpen, derivedEntityTypeRef.IsOpen(), "StructuralTypeReference.IsOpen()"); Assert.AreEqual(derivedEntityType.DeclaredStructuralProperties().Count(), derivedEntityTypeRef.DeclaredStructuralProperties().Count(), "StructuralTypeReference.DeclaredStructuralProperties()"); Assert.AreEqual(derivedEntityType.StructuralProperties().Count(), derivedEntityTypeRef.StructuralProperties().Count(), "StructuralTypeReference.StructuralProperties()"); Assert.AreEqual(derivedEntityType.DeclaredNavigationProperties().Count(), derivedEntityTypeRef.DeclaredNavigationProperties().Count(), "EntityTypeReference.DeclaredNavigationProperties()"); Assert.AreEqual(derivedEntityType.NavigationProperties().Count(), derivedEntityTypeRef.NavigationProperties().Count(), "EntityTypeReference.NavigationProperties()"); IEdmNavigationProperty result = derivedEntityTypeRef.FindNavigationProperty("_Not_Exist_"); Assert.IsNull(result, "Should not find Navigation Property {0}", "_Not_Exist_"); var navigation = derivedEntityType.NavigationProperties().First(); result = derivedEntityTypeRef.FindNavigationProperty(navigation.Name); Assert.AreEqual(navigation, result, "FindNavigationProperty({0})", navigation.Name); }
public void CreateNavigationPatchOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId, UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); Assert.NotNull(people); IEdmEntityType person = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Person"); IEdmNavigationProperty navProperty = person.DeclaredNavigationProperties().First(c => c.Name == "BestFriend"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(people), new ODataKeySegment(people.EntityType()), new ODataNavigationPropertySegment(navProperty)); // Act var operation = _operationHandler.CreateOperation(context, path); // Assert Assert.NotNull(operation); Assert.Equal("Update the best friend.", operation.Summary); Assert.Equal("Update an instance of a best friend.", operation.Description); Assert.NotNull(operation.Tags); var tag = Assert.Single(operation.Tags); Assert.Equal("People.Person", tag.Name); Assert.NotNull(operation.Parameters); Assert.Equal(1, operation.Parameters.Count); Assert.NotNull(operation.RequestBody); Assert.Equal("New navigation property values", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); var statusCode = useHTTPStatusCodeClass2XX ? "2XX" : "204"; Assert.Equal(new string[] { statusCode, "default" }, operation.Responses.Select(e => e.Key)); if (useHTTPStatusCodeClass2XX) { Assert.Single(operation.Responses[statusCode].Content); } else { Assert.Empty(operation.Responses[statusCode].Content); } if (enableOperationId) { Assert.Equal("People.UpdateBestFriend", operation.OperationId); } else { Assert.Null(operation.OperationId); } }
/// <summary> /// Retrieve the path for <see cref="IEdmNavigationProperty"/>. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <param name="currentPath">The current OData path.</param> private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationProperty, ODataPath currentPath) { Debug.Assert(navigationProperty != null); Debug.Assert(currentPath != null); // test the expandable for the navigation property. bool shouldExpand = ShouldExpandNavigationProperty(navigationProperty, currentPath); // append a navigation property. currentPath.Push(new ODataNavigationPropertySegment(navigationProperty)); AppendPath(currentPath.Clone()); if (!navigationProperty.ContainsTarget) { // Non-Contained // Single-Valued: DELETE ~/entityset/{key}/single-valued-Nav/$ref // collection-valued: DELETE ~/entityset/{key}/collection-valued-Nav/$ref?$id ={ navKey} ODataPath newPath = currentPath.Clone(); newPath.Push(ODataRefSegment.Instance); // $ref AppendPath(newPath); } // append a navigation property key. IEdmEntityType navEntityType = navigationProperty.ToEntityType(); if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { currentPath.Push(new ODataKeySegment(navEntityType)); AppendPath(currentPath.Clone()); if (!navigationProperty.ContainsTarget) { // TODO: Shall we add "$ref" after {key}, and only support delete? // ODataPath newPath = currentPath.Clone(); // newPath.Push(ODataRefSegment.Instance); // $ref // AppendPath(newPath); } } if (shouldExpand) { // expand to sub navigation properties foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties()) { if (CanFilter(subNavProperty)) { RetrieveNavigationPropertyPaths(subNavProperty, currentPath); } } } if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { currentPath.Pop(); } currentPath.Pop(); }
/// <summary> /// Retrieve the paths for <see cref="IEdmNavigationSource"/>. /// </summary> /// <param name="navigationSource">The navigation source.</param> /// <param name="convertSettings">The settings for the current conversion.</param> private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource, OpenApiConvertSettings convertSettings) { Debug.Assert(navigationSource != null); // navigation source itself ODataPath path = new(new ODataNavigationSourceSegment(navigationSource)); AppendPath(path.Clone()); IEdmEntitySet entitySet = navigationSource as IEdmEntitySet; IEdmEntityType entityType = navigationSource.EntityType(); CountRestrictionsType count = null; // for entity set, create a path with key and a $count path if (entitySet != null) { count = _model.GetRecord <CountRestrictionsType>(entitySet, CapabilitiesConstants.CountRestrictions); if (count?.Countable ?? true) // ~/entitySet/$count { CreateCountPath(path, convertSettings); } CreateTypeCastPaths(path, convertSettings, entityType, entitySet, true); // ~/entitySet/subType path.Push(new ODataKeySegment(entityType)); AppendPath(path.Clone()); CreateTypeCastPaths(path, convertSettings, entityType, entitySet, false); // ~/entitySet/{id}/subType } else if (navigationSource is IEdmSingleton singleton) { // ~/singleton/subType CreateTypeCastPaths(path, convertSettings, entityType, singleton, false); } // media entity RetrieveMediaEntityStreamPaths(entityType, path); // properties of type complex RetrieveComplexPropertyPaths(entityType, path, convertSettings); // navigation property foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) { if (CanFilter(np)) { RetrieveNavigationPropertyPaths(np, count, path, convertSettings); } } if (entitySet != null) { path.Pop(); // end of entity } path.Pop(); // end of navigation source. Debug.Assert(path.Any() == false); }
public ODataUriParserInjectionTests() { folderType = oneDriveModel.SchemaElements.OfType <IEdmComplexType>().Single(e => string.Equals(e.Name, "folder")); itemType = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "item")); specialItemType = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "specialItem")); folderProp = itemType.FindProperty("folder") as IEdmStructuralProperty; sizeProp = itemType.FindProperty("size") as IEdmStructuralProperty; driveType = oneDriveModel.SchemaElements.OfType <IEdmEntityType>().Single(e => string.Equals(e.Name, "drive")); itemsNavProp = driveType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "items"); childrenNavProp = itemType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "children"); thumbnailsNavProp = itemType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == "thumbnails"); drivesEntitySet = oneDriveModel.EntityContainer.FindEntitySet("drives"); driveSingleton = oneDriveModel.EntityContainer.FindSingleton("drive"); containedItemsNav = drivesEntitySet.FindNavigationTarget(itemsNavProp); containedthumbnailsNav = containedItemsNav.FindNavigationTarget(thumbnailsNavProp); copyOp = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "copy"); searchOp = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "search"); shareItemBindCollectionOp = oneDriveModel.SchemaElements.OfType <IEdmOperation>().LastOrDefault(o => o.Name == "sharedWithMe"); }
public void CreateNavigationPropertyPathItemReturnsCorrectPathItemWithPathParameters(bool keySegment, bool declarePathParametersOnPathItem) { // Arrange IEdmModel model = GetEdmModel(""); OpenApiConvertSettings settings = new() { DeclarePathParametersOnPathItem = declarePathParametersOnPathItem, }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() .FirstOrDefault(c => c.ContainsTarget == true && c.TargetMultiplicity() == EdmMultiplicity.Many); Assert.NotNull(property); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property)); if (keySegment) { path.Push(new ODataKeySegment(property.ToEntityType())); } // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem.Operations); Assert.NotEmpty(pathItem.Operations); Assert.NotEmpty(pathItem.Description); if (declarePathParametersOnPathItem) { Assert.NotEmpty(pathItem.Parameters); if (keySegment) { Assert.Equal(2, pathItem.Parameters.Count); // Customer ID and ContainedOrderLines Order ID } else { Assert.Equal(1, pathItem.Parameters.Count); // Customer ID } } else { Assert.Empty(pathItem.Parameters); } }
protected override void ProcessEntityType(IEdmEntityType element) { this.BeginElement <IEdmEntityType>(element, new Action <IEdmEntityType>(this.schemaWriter.WriteEntityTypeElementHeader), new Action <IEdmEntityType> [0]); if (((element.DeclaredKey != null) && (element.DeclaredKey.Count <IEdmStructuralProperty>() > 0)) && (element.BaseType == null)) { this.VisitEntityTypeDeclaredKey(element.DeclaredKey); } base.VisitProperties(element.DeclaredStructuralProperties().Cast <IEdmProperty>()); base.VisitProperties(element.DeclaredNavigationProperties().Cast <IEdmProperty>()); this.EndElement(element); }
protected override void ProcessEntityType(IEdmEntityType element) { this.BeginElement(element, this.schemaWriter.WriteEntityTypeElementHeader); if (element.DeclaredKey != null && element.DeclaredKey.Any()) { this.VisitEntityTypeDeclaredKey(element.DeclaredKey); } this.VisitProperties(element.DeclaredStructuralProperties().Cast <IEdmProperty>()); this.VisitProperties(element.DeclaredNavigationProperties().Cast <IEdmProperty>()); this.EndElement(element); }
public void CreateNavigationRefPostOperationReturnsCorrectOperation(bool enableOperationId, bool useHTTPStatusCodeClass2XX) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId, UseSuccessStatusCodeRange = useHTTPStatusCodeClass2XX }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); Assert.NotNull(people); IEdmEntityType person = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Person"); IEdmNavigationProperty navProperty = person.DeclaredNavigationProperties().First(c => c.Name == "Trips"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(people), new ODataKeySegment(people.EntityType()), new ODataNavigationPropertySegment(navProperty), ODataRefSegment.Instance); // Act var operation = _operationHandler.CreateOperation(context, path); // Assert Assert.NotNull(operation); Assert.Equal("Create a trip.", operation.Summary); Assert.Equal("Create a new trip.", operation.Description); Assert.NotNull(operation.Tags); var tag = Assert.Single(operation.Tags); Assert.Equal("People.Trip", tag.Name); Assert.NotNull(operation.Parameters); Assert.NotEmpty(operation.Parameters); Assert.NotNull(operation.RequestBody); Assert.Equal(Models.ReferenceType.RequestBody, operation.RequestBody.Reference.Type); Assert.Equal(Common.Constants.ReferencePostRequestBodyName, operation.RequestBody.Reference.Id); Assert.Equal(2, operation.Responses.Count); Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { Assert.Equal("People.CreateRefTrips", operation.OperationId); } else { Assert.Null(operation.OperationId); } }
public void CreateNavigationRefPutOperationReturnsCorrectOperation(bool enableOperationId) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet people = model.EntityContainer.FindEntitySet("People"); Assert.NotNull(people); IEdmEntityType person = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Person"); IEdmNavigationProperty navProperty = person.DeclaredNavigationProperties().First(c => c.Name == "BestFriend"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(people), new ODataKeySegment(people.EntityType()), new ODataNavigationPropertySegment(navProperty), ODataRefSegment.Instance); // Act var operation = _operationHandler.CreateOperation(context, path); // Assert Assert.NotNull(operation); Assert.Equal("Update the ref of navigation property BestFriend in People", operation.Summary); Assert.NotNull(operation.Tags); var tag = Assert.Single(operation.Tags); Assert.Equal("People.Person", tag.Name); Assert.NotNull(operation.Parameters); Assert.Equal(1, operation.Parameters.Count); Assert.NotNull(operation.RequestBody); Assert.Equal("New navigation property ref values", operation.RequestBody.Description); Assert.Equal(2, operation.Responses.Count); Assert.Equal(new string[] { "204", "default" }, operation.Responses.Select(e => e.Key)); if (enableOperationId) { Assert.Equal("People.UpdateRefBestFriend", operation.OperationId); } else { Assert.Null(operation.OperationId); } }
public void CreateLinksForSingleValuedNavigationProperties() { // Arrange IEdmModel model = EdmModelHelper.GraphBetaModel; OpenApiConvertSettings settings = new() { ShowLinks = true, ExpandDerivedTypesNavigationProperties = false }; ODataContext context = new(model, settings); IEdmSingleton admin = model.EntityContainer.FindSingleton("admin"); Assert.NotNull(admin); IEdmEntityType adminEntityType = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "admin"); IEdmNavigationProperty navProperty = adminEntityType.DeclaredNavigationProperties().First(c => c.Name == "serviceAnnouncement"); ODataPath path = new( new ODataNavigationSourceSegment(admin), new ODataNavigationPropertySegment(navProperty)); // Act IDictionary <string, OpenApiLink> links = context.CreateLinks( entityType: navProperty.ToEntityType(), entityName: adminEntityType.Name, entityKind: navProperty.PropertyKind.ToString(), path: path, navPropOperationId: "admin.ServiceAnnouncement"); // Assert Assert.NotNull(links); Assert.Equal(3, links.Count); Assert.Collection(links, item => { Assert.Equal("healthOverviews", item.Key); Assert.Equal("admin.ServiceAnnouncement.ListHealthOverviews", item.Value.OperationId); }, item => { Assert.Equal("issues", item.Key); Assert.Equal("admin.ServiceAnnouncement.ListIssues", item.Value.OperationId); }, item => { Assert.Equal("messages", item.Key); Assert.Equal("admin.ServiceAnnouncement.ListMessages", item.Value.OperationId); }); }
public void CreateNavigationPropertyRefPathItemReturnsCorrectPathItem(bool collectionNav, OperationType[] expected) { // Arrange IEdmModel model = GetEdmModel(""); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmNavigationProperty property = entityType.DeclaredNavigationProperties() .FirstOrDefault(c => !c.ContainsTarget && (collectionNav ? c.TargetMultiplicity() == EdmMultiplicity.Many : c.TargetMultiplicity() != EdmMultiplicity.Many)); Assert.NotNull(property); ODataPath path; if (collectionNav && expected.Contains(OperationType.Delete)) { // DELETE ~/entityset/{key}/collection-valued-Nav/{key}/$ref path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property), new ODataKeySegment(property.ToEntityType()), ODataRefSegment.Instance); } else { path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property), ODataRefSegment.Instance); } // 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(o => o.Key)); Assert.NotEmpty(pathItem.Description); }
public void CreateOrderByAndSelectAndExpandParametersWorks() { // Arrange IEdmModel model = GetEdmModel(); ODataContext context = new ODataContext(model, new OpenApiConvertSettings()); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); IEdmSingleton singleton = model.EntityContainer.FindSingleton("Catalog"); IEdmEntityType entityType = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer"); IEdmNavigationProperty navigationProperty = entityType.DeclaredNavigationProperties().First(c => c.Name == "Addresses"); // Act & Assert // OrderBy string orderByItemsText = @"""enum"": [ ""ID"", ""ID desc"" ],"; VerifyCreateOrderByParameter(entitySet, context, orderByItemsText); VerifyCreateOrderByParameter(singleton, context); VerifyCreateOrderByParameter(navigationProperty, context); // Select string selectItemsText = @"""enum"": [ ""ID"", ""Addresses"" ],"; VerifyCreateSelectParameter(entitySet, context, selectItemsText); VerifyCreateSelectParameter(singleton, context); VerifyCreateSelectParameter(navigationProperty, context); // Expand string expandItemsText = @"""enum"": [ ""*"", ""Addresses"" ],"; VerifyCreateExpandParameter(entitySet, context, expandItemsText); string expandItemsDefaultText = @"""enum"": [ ""*"" ],"; VerifyCreateExpandParameter(singleton, context, expandItemsDefaultText); VerifyCreateExpandParameter(navigationProperty, context, expandItemsDefaultText); }
public static bool IsNavigationTypeOverload(this IEdmModel model, IEdmEntityType entityType, IEdmNavigationProperty navigationProperty) { Utils.CheckArgumentNull(model, nameof(model)); Utils.CheckArgumentNull(entityType, nameof(entityType)); Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty)); int count = 0; IEdmEntityType nvaEntityType = navigationProperty.ToEntityType(); foreach (var np in entityType.DeclaredNavigationProperties()) { if (np.ToEntityType() == nvaEntityType) { count++; } } return(count == 0); }
public void CreateMediaEntityPathItemReturnsCorrectItem() { // Arrange IEdmModel model = GetEdmModel(""); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); IEdmSingleton singleton = model.EntityContainer.FindSingleton("me"); Assert.NotNull(entitySet); // guard Assert.NotNull(singleton); IEdmEntityType entityType = entitySet.EntityType(); IEdmStructuralProperty sp = entityType.DeclaredStructuralProperties().First(c => c.Name == "Logo"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataStreamPropertySegment(sp.Name)); IEdmEntityType user = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "user"); IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(singleton), new ODataNavigationPropertySegment(navProperty), new ODataStreamContentSegment()); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); var pathItem2 = _pathItemHandler.CreatePathItem(context, path2); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem2); Assert.NotNull(pathItem.Operations); Assert.NotNull(pathItem2.Operations); Assert.NotEmpty(pathItem.Operations); Assert.NotEmpty(pathItem2.Operations); Assert.Equal(2, pathItem.Operations.Count); Assert.Equal(2, pathItem2.Operations.Count); Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Put }, pathItem.Operations.Select(o => o.Key)); Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Put }, pathItem2.Operations.Select(o => o.Key)); Assert.NotEmpty(pathItem.Description); }
public void CreatePathItemForNavigationPropertyWithOutOfLineRestrictionAnnotations() { // Arrange IEdmModel model = EdmModelHelper.GraphBetaModel; OpenApiConvertSettings settings = new() { ExpandDerivedTypesNavigationProperties = false }; ODataContext context = new(model, settings); IEdmSingleton ipSingleton = model.EntityContainer.FindSingleton("informationProtection"); Assert.NotNull(ipSingleton); IEdmEntityType ipEntity = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "informationProtection"); Assert.NotNull(ipEntity); IEdmNavigationProperty bitlockerNavProp = ipEntity.DeclaredNavigationProperties().First(c => c.Name == "bitlocker"); Assert.NotNull(bitlockerNavProp); IEdmEntityType bitlockerEntity = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "bitlocker"); Assert.NotNull(bitlockerEntity); IEdmNavigationProperty rkNavProp = bitlockerEntity.DeclaredNavigationProperties().First(c => c.Name == "recoveryKeys"); Assert.NotNull(rkNavProp); ODataPath path = new(new ODataNavigationSourceSegment(ipSingleton), new ODataNavigationPropertySegment(bitlockerNavProp), new ODataNavigationPropertySegment(rkNavProp), new ODataKeySegment(rkNavProp.ToEntityType())); Assert.NotNull(path); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem.Operations); Assert.Single(pathItem.Operations); Assert.Equal(OperationType.Get, pathItem.Operations.FirstOrDefault().Key); }
private void VisitEntityType(IEdmEntityType entity) { string qualifiedName = entity.FullTypeName(); if (_types.ContainsKey(qualifiedName)) { return; // processed } MetaEntityType metaEntity = new MetaEntityType(); metaEntity.QualifiedName = qualifiedName; metaEntity.Name = entity.Name; metaEntity.Abstract = entity.IsAbstract; metaEntity.OpenType = entity.IsOpen; metaEntity.HasStream = entity.HasStream; _types[qualifiedName] = metaEntity; VisitProperties(metaEntity, entity.DeclaredProperties); VisitNavProperties(metaEntity, entity.DeclaredNavigationProperties()); }
/// <summary> /// Retrieve the path for <see cref="IEdmNavigationProperty"/>. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <param name="currentPath">The current OData path.</param> private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationProperty, ODataPath currentPath) { Debug.Assert(navigationProperty != null); Debug.Assert(currentPath != null); // test the expandable for the navigation property. bool shouldExpand = ShouldExpandNavigationProperty(navigationProperty, currentPath); // append a navigation property. currentPath.Push(new ODataNavigationPropertySegment(navigationProperty)); AppendPath(currentPath.Clone()); // append a navigation property key. IEdmEntityType navEntityType = navigationProperty.ToEntityType(); if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { currentPath.Push(new ODataKeySegment(navEntityType)); AppendPath(currentPath.Clone()); } if (shouldExpand) { // expand to sub navigation properties foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties()) { if (CanFilter(subNavProperty)) { RetrieveNavigationPropertyPaths(subNavProperty, currentPath); } } } if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { currentPath.Pop(); } currentPath.Pop(); }
private static ODataPath CreatePath(IEdmNavigationSource navigationSource, string navigationPropertyPath, bool single) { Assert.NotNull(navigationSource); Assert.NotNull(navigationPropertyPath); IEdmEntityType previousEntityType = navigationSource.EntityType(); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(navigationSource), new ODataKeySegment(previousEntityType)); string[] npPaths = navigationPropertyPath.Split('/'); IEdmNavigationProperty previousProperty = null; foreach (string npPath in npPaths) { IEdmNavigationProperty property = previousEntityType.DeclaredNavigationProperties().FirstOrDefault(p => p.Name == npPath); Assert.NotNull(property); if (previousProperty != null) { if (previousProperty.TargetMultiplicity() == EdmMultiplicity.Many) { path.Push(new ODataKeySegment(previousProperty.ToEntityType())); } } path.Push(new ODataNavigationPropertySegment(property)); previousProperty = property; previousEntityType = property.ToEntityType(); } if (single) { if (previousProperty.TargetMultiplicity() == EdmMultiplicity.Many) { path.Push(new ODataKeySegment(previousProperty.ToEntityType())); } } return(path); }
/// <summary> /// Retrieve the paths for <see cref="IEdmNavigationSource"/>. /// </summary> /// <param name="navigationSource">The navigation source.</param> private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource) { Debug.Assert(navigationSource != null); // navigation source itself ODataPath path = new ODataPath(new ODataNavigationSourceSegment(navigationSource)); AppendPath(path.Clone()); IEdmEntitySet entitySet = navigationSource as IEdmEntitySet; IEdmEntityType entityType = navigationSource.EntityType(); // for entity set, create a path with key if (entitySet != null) { path.Push(new ODataKeySegment(entityType)); AppendPath(path.Clone()); } // media entity RetrieveMediaEntityStreamPaths(entityType, path); // navigation property foreach (IEdmNavigationProperty np in entityType.DeclaredNavigationProperties()) { if (CanFilter(np)) { RetrieveNavigationPropertyPaths(np, path); } } if (entitySet != null) { path.Pop(); // end of entity } path.Pop(); // end of navigation source. Debug.Assert(path.Any() == false); }
private void VerifyPathItemOperationsForStreamContentSegment(string annotation, OperationType[] expected) { // Arrange IEdmModel model = GetEdmModel(annotation); ODataContext context = new ODataContext(model); IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Todos"); IEdmSingleton singleton = model.EntityContainer.FindSingleton("me"); Assert.NotNull(entitySet); // guard Assert.NotNull(singleton); IEdmEntityType entityType = entitySet.EntityType(); IEdmEntityType user = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "user"); IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(singleton), new ODataNavigationPropertySegment(navProperty), new ODataStreamContentSegment()); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataStreamContentSegment()); // Act var pathItem = _pathItemHandler.CreatePathItem(context, path); var pathItem2 = _pathItemHandler.CreatePathItem(context, path2); // Assert Assert.NotNull(pathItem); Assert.NotNull(pathItem2); Assert.NotNull(pathItem.Operations); Assert.NotNull(pathItem2.Operations); Assert.NotEmpty(pathItem.Operations); Assert.NotEmpty(pathItem2.Operations); Assert.Equal(expected, pathItem.Operations.Select(e => e.Key)); Assert.Equal(expected, pathItem2.Operations.Select(e => e.Key)); }
public void CreateNavigationPatchOperationReturnsSecurityForUpdateRestrictions(bool enableAnnotation) { string annotation = @"<Annotation Term=""Org.OData.Capabilities.V1.NavigationRestrictions""> <Record> <PropertyValue Property=""RestrictedProperties"" > <Collection> <Record> <PropertyValue Property=""NavigationProperty"" NavigationPropertyPath=""Orders"" /> <PropertyValue Property=""UpdateRestrictions"" > <Record> <PropertyValue Property=""Permissions""> <Collection> <Record> <PropertyValue Property=""SchemeName"" String=""Delegated (work or school account)"" /> <PropertyValue Property=""Scopes""> <Collection> <Record> <PropertyValue Property=""Scope"" String=""User.ReadBasic.All"" /> </Record> <Record> <PropertyValue Property=""Scope"" String=""User.Read.All"" /> </Record> </Collection> </PropertyValue> </Record> <Record> <PropertyValue Property=""SchemeName"" String=""Application"" /> <PropertyValue Property=""Scopes""> <Collection> <Record> <PropertyValue Property=""Scope"" String=""User.Read.All"" /> </Record> <Record> <PropertyValue Property=""Scope"" String=""Directory.Read.All"" /> </Record> </Collection> </PropertyValue> </Record> </Collection> </PropertyValue> <PropertyValue Property=""Description"" String=""A brief description of GET '/me' request."" /> <PropertyValue Property=""CustomHeaders""> <Collection> <Record> <PropertyValue Property=""Name"" String=""odata-debug"" /> <PropertyValue Property=""Description"" String=""Debug support for OData services"" /> <PropertyValue Property=""Required"" Bool=""false"" /> <PropertyValue Property=""ExampleValues""> <Collection> <Record> <PropertyValue Property=""Value"" String=""html"" /> <PropertyValue Property=""Description"" String=""Service responds with self-contained..."" /> </Record> <Record> <PropertyValue Property=""Value"" String=""json"" /> <PropertyValue Property=""Description"" String=""Service responds with JSON document..."" /> </Record> </Collection> </PropertyValue> </Record> </Collection> </PropertyValue> </Record> </PropertyValue> </Record> </Collection> </PropertyValue> </Record> </Annotation>"; // Arrange IEdmModel edmModel = NavigationPropertyPathItemHandlerTest.GetEdmModel(enableAnnotation ? annotation : ""); Assert.NotNull(edmModel); ODataContext context = new ODataContext(edmModel); IEdmEntitySet entitySet = edmModel.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // guard IEdmEntityType entityType = entitySet.EntityType(); IEdmNavigationProperty property = entityType.DeclaredNavigationProperties().FirstOrDefault(c => c.Name == "Orders"); Assert.NotNull(property); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entityType), new ODataNavigationPropertySegment(property), new ODataKeySegment(property.DeclaringEntityType())); // Act var operation = _operationHandler.CreateOperation(context, path); // Assert Assert.NotNull(operation); Assert.NotNull(operation.Security); if (enableAnnotation) { Assert.Equal(2, operation.Security.Count); string json = operation.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); Assert.Contains(@" ""security"": [ { ""Delegated (work or school account)"": [ ""User.ReadBasic.All"", ""User.Read.All"" ] }, { ""Application"": [ ""User.Read.All"", ""Directory.Read.All"" ] } ],".ChangeLineBreaks(), json); // with custom header Assert.Contains(@" { ""name"": ""odata-debug"", ""in"": ""header"", ""description"": ""Debug support for OData services"", ""schema"": { ""type"": ""string"" }, ""examples"": { ""example-1"": { ""description"": ""Service responds with self-contained..."", ""value"": ""html"" }, ""example-2"": { ""description"": ""Service responds with JSON document..."", ""value"": ""json"" } } }".ChangeLineBreaks(), json); } else { Assert.Empty(operation.Security); } }
public void CreateLinksForCollectionValuedNavigationProperties() { // Arrange IEdmModel model = EdmModelHelper.GraphBetaModel; OpenApiConvertSettings settings = new() { ShowLinks = true, ExpandDerivedTypesNavigationProperties = false }; ODataContext context = new(model, settings); IEdmSingleton singleton = model.EntityContainer.FindSingleton("admin"); Assert.NotNull(singleton); IEdmEntityType singletonEntityType = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "admin"); IEdmNavigationProperty navProperty = singletonEntityType.DeclaredNavigationProperties().First(c => c.Name == "serviceAnnouncement"); IEdmNavigationProperty navProperty2 = navProperty.ToEntityType().DeclaredNavigationProperties().First(c => c.Name == "messages"); ODataPath path = new( new ODataNavigationSourceSegment(singleton), new ODataNavigationPropertySegment(navProperty), new ODataNavigationPropertySegment(navProperty2)); // Act IDictionary <string, OpenApiLink> links = context.CreateLinks( entityType: navProperty2.ToEntityType(), entityName: singletonEntityType.Name, entityKind: navProperty2.PropertyKind.ToString(), path: path); // Assert Assert.NotNull(links); Assert.Equal(6, links.Count); // Links will reference Operations and OperationImports Assert.Collection(links, item => { Assert.Equal("archive", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.archive", item.Value.OperationId); }, item => { Assert.Equal("favorite", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.favorite", item.Value.OperationId); }, item => { Assert.Equal("markRead", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.markRead", item.Value.OperationId); }, item => { Assert.Equal("markUnread", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.markUnread", item.Value.OperationId); }, item => { Assert.Equal("unarchive", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.unarchive", item.Value.OperationId); }, item => { Assert.Equal("unfavorite", item.Key); Assert.Equal("admin.serviceAnnouncement.messages.unfavorite", item.Value.OperationId); }); }
/// <summary> /// Retrieve the path for <see cref="IEdmNavigationProperty"/>. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <param name="count">The count restrictions.</param> /// <param name="currentPath">The current OData path.</param> /// <param name="convertSettings">The settings for the current conversion.</param> /// <param name="visitedNavigationProperties">A stack that holds the visited navigation properties in the <paramref name="currentPath"/>.</param> private void RetrieveNavigationPropertyPaths( IEdmNavigationProperty navigationProperty, CountRestrictionsType count, ODataPath currentPath, OpenApiConvertSettings convertSettings, Stack <string> visitedNavigationProperties = null) { Debug.Assert(navigationProperty != null); Debug.Assert(currentPath != null); if (visitedNavigationProperties == null) { visitedNavigationProperties = new(); } string navPropFullyQualifiedName = $"{navigationProperty.DeclaringType.FullTypeName()}/{navigationProperty.Name}"; // Check whether the navigation property has already been navigated in the path. if (visitedNavigationProperties.Contains(navPropFullyQualifiedName)) { return; } // Get the annotatable navigation source for this navigation property. IEdmVocabularyAnnotatable annotatableNavigationSource = (currentPath.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable; NavigationRestrictionsType navSourceRestrictionType = null; NavigationRestrictionsType navPropRestrictionType = null; // Get the NavigationRestrictions referenced by this navigation property: Can be defined in the navigation source or in-lined in the navigation property. if (annotatableNavigationSource != null) { navSourceRestrictionType = _model.GetRecord <NavigationRestrictionsType>(annotatableNavigationSource, CapabilitiesConstants.NavigationRestrictions); navPropRestrictionType = _model.GetRecord <NavigationRestrictionsType>(navigationProperty, CapabilitiesConstants.NavigationRestrictions); } NavigationPropertyRestriction restriction = navSourceRestrictionType?.RestrictedProperties? .FirstOrDefault(r => r.NavigationProperty == currentPath.NavigationPropertyPath(navigationProperty.Name)) ?? navPropRestrictionType?.RestrictedProperties?.FirstOrDefault(); // Check whether the navigation property should be part of the path if (!EdmModelHelper.NavigationRestrictionsAllowsNavigability(navSourceRestrictionType, restriction) || !EdmModelHelper.NavigationRestrictionsAllowsNavigability(navPropRestrictionType, restriction)) { return; } // Whether to expand the navigation property. bool shouldExpand = navigationProperty.ContainsTarget; // Append a navigation property. currentPath.Push(new ODataNavigationPropertySegment(navigationProperty)); AppendPath(currentPath.Clone()); visitedNavigationProperties.Push(navPropFullyQualifiedName); // Check whether a collection-valued navigation property should be indexed by key value(s). bool indexableByKey = restriction?.IndexableByKey ?? true; if (indexableByKey) { IEdmEntityType navEntityType = navigationProperty.ToEntityType(); var targetsMany = navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many; var propertyPath = navigationProperty.GetPartnerPath()?.Path; var propertyPathIsEmpty = string.IsNullOrEmpty(propertyPath); if (targetsMany) { if (propertyPathIsEmpty || (count?.IsNonCountableNavigationProperty(propertyPath) ?? true)) { // ~/entityset/{key}/collection-valued-Nav/$count CreateCountPath(currentPath, convertSettings); } } // ~/entityset/{key}/collection-valued-Nav/subtype // ~/entityset/{key}/single-valued-Nav/subtype CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, targetsMany); if ((navSourceRestrictionType?.Referenceable ?? false) || (navPropRestrictionType?.Referenceable ?? false)) { // Referenceable navigation properties // Single-Valued: ~/entityset/{key}/single-valued-Nav/$ref // Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id='{navKey}' CreateRefPath(currentPath); if (targetsMany) { // Collection-valued: DELETE ~/entityset/{key}/collection-valued-Nav/{key}/$ref currentPath.Push(new ODataKeySegment(navEntityType)); CreateRefPath(currentPath); CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype } // Get possible stream paths for the navigation entity type RetrieveMediaEntityStreamPaths(navEntityType, currentPath); // Get the paths for the navigation property entity type properties of type complex RetrieveComplexPropertyPaths(navEntityType, currentPath, convertSettings); } else { // append a navigation property key. if (targetsMany) { currentPath.Push(new ODataKeySegment(navEntityType)); AppendPath(currentPath.Clone()); CreateTypeCastPaths(currentPath, convertSettings, navEntityType, navigationProperty, false); // ~/entityset/{key}/collection-valued-Nav/{id}/subtype } // Get possible stream paths for the navigation entity type RetrieveMediaEntityStreamPaths(navEntityType, currentPath); // Get the paths for the navigation property entity type properties of type complex RetrieveComplexPropertyPaths(navEntityType, currentPath, convertSettings); if (shouldExpand) { // expand to sub navigation properties foreach (IEdmNavigationProperty subNavProperty in navEntityType.DeclaredNavigationProperties()) { if (CanFilter(subNavProperty)) { RetrieveNavigationPropertyPaths(subNavProperty, count, currentPath, convertSettings, visitedNavigationProperties); } } } } if (targetsMany) { currentPath.Pop(); } } currentPath.Pop(); visitedNavigationProperties.Pop(); }
private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType, string identifier) { return(entityType.DeclaredNavigationProperties().FirstOrDefault(x => x.Name.Equals(identifier))); }
private void CreateNavigationPropertiesForStockEntity(IEdmEntityType edmType, IEdmModel edmModel, EdmModel stockModel) { var stockType = (EdmEntityType)stockModel.FindType(edmType.FullName()); foreach (var edmNavigation in edmType.DeclaredNavigationProperties()) { var stockToRoleType = (EdmEntityType)stockModel.FindType(edmNavigation.ToEntityType().FullName()); if (stockType.FindProperty(edmNavigation.Name) == null) { Func <IEnumerable <IEdmStructuralProperty>, IEnumerable <IEdmStructuralProperty> > createDependentProperties = (dependentProps) => { if (dependentProps == null) { return(null); } var stockDependentProperties = new List <IEdmStructuralProperty>(); foreach (var dependentProperty in dependentProps) { var stockDepProp = edmNavigation.DependentProperties() != null?stockType.FindProperty(dependentProperty.Name) : stockToRoleType.FindProperty(dependentProperty.Name); stockDependentProperties.Add((IEdmStructuralProperty)stockDepProp); } return(stockDependentProperties); }; Func <IEdmReferentialConstraint, IEdmEntityType, IEnumerable <IEdmStructuralProperty> > createPrincipalProperties = (refConstraint, principalType) => { if (refConstraint == null) { return(null); } return(refConstraint.PropertyPairs.Select(p => (IEdmStructuralProperty)principalType.FindProperty(p.PrincipalProperty.Name))); }; var propertyInfo = new EdmNavigationPropertyInfo() { Name = edmNavigation.Name, Target = stockToRoleType, TargetMultiplicity = edmNavigation.TargetMultiplicity(), DependentProperties = createDependentProperties(edmNavigation.DependentProperties()), PrincipalProperties = createPrincipalProperties(edmNavigation.ReferentialConstraint, stockToRoleType), ContainsTarget = edmNavigation.ContainsTarget, OnDelete = edmNavigation.OnDelete }; bool bidirectional = edmNavigation.Partner != null && edmNavigation.ToEntityType().FindProperty(edmNavigation.Partner.Name) != null; if (bidirectional) { var partnerInfo = new EdmNavigationPropertyInfo() { Name = edmNavigation.Partner.Name, TargetMultiplicity = edmNavigation.Partner.TargetMultiplicity(), DependentProperties = createDependentProperties(edmNavigation.Partner.DependentProperties()), PrincipalProperties = createPrincipalProperties(edmNavigation.Partner.ReferentialConstraint, stockType), ContainsTarget = edmNavigation.Partner.ContainsTarget, OnDelete = edmNavigation.Partner.OnDelete }; stockType.AddBidirectionalNavigation(propertyInfo, partnerInfo); } else { stockType.AddUnidirectionalNavigation(propertyInfo); } } } }
private void VerifyMediaEntityPutOperation(string annotation, bool enableOperationId) { // Arrange IEdmModel model = MediaEntityGetOperationHandlerTests.GetEdmModel(annotation); OpenApiConvertSettings settings = new OpenApiConvertSettings { EnableOperationId = enableOperationId }; ODataContext context = new ODataContext(model, settings); IEdmEntitySet todos = model.EntityContainer.FindEntitySet("Todos"); IEdmSingleton me = model.EntityContainer.FindSingleton("me"); Assert.NotNull(todos); IEdmEntityType todo = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Todo"); IEdmStructuralProperty sp = todo.DeclaredStructuralProperties().First(c => c.Name == "Logo"); ODataPath path = new ODataPath(new ODataNavigationSourceSegment(todos), new ODataKeySegment(todos.EntityType()), new ODataStreamPropertySegment(sp.Name)); IEdmEntityType user = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "user"); IEdmNavigationProperty navProperty = user.DeclaredNavigationProperties().First(c => c.Name == "photo"); ODataPath path2 = new ODataPath(new ODataNavigationSourceSegment(me), new ODataNavigationPropertySegment(navProperty), new ODataStreamContentSegment()); // Act var putOperation = _operationalHandler.CreateOperation(context, path); var putOperation2 = _operationalHandler.CreateOperation(context, path2); // Assert Assert.NotNull(putOperation); Assert.NotNull(putOperation2); Assert.Equal("Update media content for Todo in Todos", putOperation.Summary); Assert.Equal("Update media content for the navigation property photo in me", putOperation2.Summary); Assert.NotNull(putOperation.Tags); Assert.NotNull(putOperation2.Tags); var tag = Assert.Single(putOperation.Tags); var tag2 = Assert.Single(putOperation2.Tags); Assert.Equal("Todos.Todo", tag.Name); Assert.Equal("me.profilePhoto", tag2.Name); Assert.NotNull(putOperation.Responses); Assert.NotNull(putOperation2.Responses); Assert.Equal(2, putOperation.Responses.Count); Assert.Equal(2, putOperation2.Responses.Count); Assert.Equal(new[] { "204", "default" }, putOperation.Responses.Select(r => r.Key)); Assert.Equal(new[] { "204", "default" }, putOperation2.Responses.Select(r => r.Key)); if (!string.IsNullOrEmpty(annotation)) { Assert.Equal(2, putOperation.RequestBody.Content.Keys.Count); Assert.True(putOperation.RequestBody.Content.ContainsKey("image/png")); Assert.True(putOperation.RequestBody.Content.ContainsKey("image/jpeg")); Assert.Equal(1, putOperation2.RequestBody.Content.Keys.Count); Assert.True(putOperation2.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); } else { Assert.Equal(1, putOperation.RequestBody.Content.Keys.Count); Assert.Equal(1, putOperation2.RequestBody.Content.Keys.Count); Assert.True(putOperation.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); Assert.True(putOperation2.RequestBody.Content.ContainsKey(Constants.ApplicationOctetStreamMediaType)); } if (enableOperationId) { Assert.Equal("Todos.Todo.UpdateLogo", putOperation.OperationId); Assert.Equal("me.UpdatePhotoContent", putOperation2.OperationId); } else { Assert.Null(putOperation.OperationId); Assert.Null(putOperation2.OperationId); } }
private void CreateNavigationPropertiesForStockEntity(IEdmEntityType edmType, IEdmModel edmModel, EdmModel stockModel) { var stockType = (EdmEntityType)stockModel.FindType(edmType.FullName()); foreach (var edmNavigation in edmType.DeclaredNavigationProperties()) { var stockToRoleType = (EdmEntityType)stockModel.FindType(edmNavigation.ToEntityType().FullName()); if (stockType.FindProperty(edmNavigation.Name) == null) { Func<IEnumerable<IEdmStructuralProperty>, IEnumerable<IEdmStructuralProperty>> createDependentProperties = (dependentProps) => { if (dependentProps == null) { return null; } var stockDependentProperties = new List<IEdmStructuralProperty>(); foreach (var dependentProperty in dependentProps) { var stockDepProp = edmNavigation.DependentProperties() != null ? stockType.FindProperty(dependentProperty.Name) : stockToRoleType.FindProperty(dependentProperty.Name); stockDependentProperties.Add((IEdmStructuralProperty)stockDepProp); } return stockDependentProperties; }; Func<IEdmReferentialConstraint, IEdmEntityType, IEnumerable<IEdmStructuralProperty>> createPrincipalProperties = (refConstraint, principalType) => { if (refConstraint == null) { return null; } return refConstraint.PropertyPairs.Select(p => (IEdmStructuralProperty)principalType.FindProperty(p.PrincipalProperty.Name)); }; var propertyInfo = new EdmNavigationPropertyInfo() { Name = edmNavigation.Name, Target = stockToRoleType, TargetMultiplicity = edmNavigation.TargetMultiplicity(), DependentProperties = createDependentProperties(edmNavigation.DependentProperties()), PrincipalProperties = createPrincipalProperties(edmNavigation.ReferentialConstraint, stockToRoleType), ContainsTarget = edmNavigation.ContainsTarget, OnDelete = edmNavigation.OnDelete }; bool bidirectional = edmNavigation.Partner != null && edmNavigation.ToEntityType().FindProperty(edmNavigation.Partner.Name) != null; if (bidirectional) { var partnerInfo = new EdmNavigationPropertyInfo() { Name = edmNavigation.Partner.Name, TargetMultiplicity = edmNavigation.Partner.TargetMultiplicity(), DependentProperties = createDependentProperties(edmNavigation.Partner.DependentProperties()), PrincipalProperties = createPrincipalProperties(edmNavigation.Partner.ReferentialConstraint, stockType), ContainsTarget = edmNavigation.Partner.ContainsTarget, OnDelete = edmNavigation.Partner.OnDelete }; stockType.AddBidirectionalNavigation(propertyInfo, partnerInfo); } else { stockType.AddUnidirectionalNavigation(propertyInfo); } } } }