/// <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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 4
0
        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);
            }
        }
Ejemplo n.º 6
0
        /// <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");
 }
Ejemplo n.º 9
0
        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);
 }
Ejemplo n.º 11
0
        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);
            }
        }
Ejemplo n.º 14
0
        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);
            });
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 19
0
        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);
        }
Ejemplo n.º 20
0
        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());
        }
Ejemplo n.º 21
0
        /// <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();
        }
Ejemplo n.º 22
0
        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);
        }
Ejemplo n.º 23
0
        /// <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));
        }
Ejemplo n.º 25
0
        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);
            }
        }
Ejemplo n.º 26
0
        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();
        }
Ejemplo n.º 28
0
 private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType, string identifier)
 {
     return(entityType.DeclaredNavigationProperties().FirstOrDefault(x => x.Name.Equals(identifier)));
 }
Ejemplo n.º 29
0
        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);
            }
        }
Ejemplo n.º 31
0
        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);
                    }
                }
            }
        }