public void WriteObjectInline_Respects_DollarSelect()
        {
            // Arrange
            Mock <ODataWriter> writer = new Mock <ODataWriter>();

            writer
            .Setup(w => w.WriteStart(It.IsAny <ODataEntry>()))
            .Callback((ODataEntry entry) =>
            {
                Assert.Equal("ID", entry.Properties.Single().Name);
            });

            // Act
            ODataQueryProjectionNode rootNode = new ODataQueryProjectionNode
            {
                Name     = "",
                NodeType = _customerSet.ElementType,
                Selects  =
                {
                    new ODataQueryProjectionNode
                    {
                        Name     = "ID",
                        NodeType = _model.FindType("Edm.Int32")
                    }
                }
            };

            _writeContext.CurrentProjectionNode = rootNode;
            _writeContext.RootProjectionNode    = rootNode;
            _serializer.WriteObjectInline(_customer, writer.Object, _writeContext);
        }
        public void WriteObjectInline_Respects_DollarExpand()
        {
            // Arrange
            bool order1Written        = false;
            bool order2Written        = false;
            Mock <ODataWriter> writer = new Mock <ODataWriter>();

            writer
            .Setup(w => w.WriteStart(It.IsAny <ODataEntry>()))
            .Callback((ODataEntry entry) =>
            {
                if (entry.TypeName == "Default.Order")
                {
                    int id = (int)entry.Properties.Where(p => p.Name == "ID").Single().Value;
                    if (id == 1)
                    {
                        order1Written = true;
                    }
                    else if (id == 2)
                    {
                        order2Written = true;
                    }
                    else
                    {
                        Assert.True(false);
                    }
                }
            });

            ODataQueryProjectionNode rootNode = new ODataQueryProjectionNode
            {
                Name     = "",
                NodeType = _customerSet.ElementType,
                Expands  =
                {
                    new ODataQueryProjectionNode
                    {
                        NodeType = _model.FindDeclaredType("Default.Order"),
                        Name     = "Orders"
                    }
                }
            };

            _customer.Orders.Add(new Order {
                ID = 1, Name = "1"
            });
            _customer.Orders.Add(new Order {
                ID = 2, Name = "2"
            });
            _writeContext.CurrentProjectionNode = rootNode;
            _writeContext.RootProjectionNode    = rootNode;

            // Act
            _serializer.WriteObjectInline(_customer, writer.Object, _writeContext);

            // Assert
            Assert.True(order1Written);
            Assert.True(order2Written);
        }
        private void WriteNavigationLinks(EntityInstanceContext context, ODataWriter writer, ODataSerializerWriteContext writeContext)
        {
            foreach (IEdmNavigationProperty navProperty in _edmEntityTypeReference.NavigationProperties())
            {
                IEdmTypeReference propertyType  = navProperty.Type;
                object            propertyValue = context.EntityInstance.GetType().GetProperty(navProperty.Name).GetValue(context.EntityInstance, index: null);

                if (writeContext.EntitySet != null)
                {
                    IEdmEntitySet         currentEntitySet = writeContext.EntitySet.FindNavigationTarget(navProperty);
                    IEntitySetLinkBuilder linkBuilder      = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet);

                    ODataNavigationLink navigationLink = new ODataNavigationLink
                    {
                        IsCollection = propertyType.IsCollection(),
                        Name         = navProperty.Name,
                        Url          = linkBuilder.BuildNavigationLink(context, navProperty)
                    };

                    ODataQueryProjectionNode expandNode = null;
                    if (writeContext.CurrentProjectionNode != null)
                    {
                        expandNode = writeContext.CurrentProjectionNode.Expands.FirstOrDefault(p => p.Name == navProperty.Name);
                    }

                    if (expandNode != null && propertyValue != null)
                    {
                        writer.WriteStart(navigationLink);
                        ODataSerializer serializer = SerializerProvider.GetEdmTypeSerializer(propertyType);
                        if (serializer == null)
                        {
                            throw Error.NotSupported(SRResources.TypeCannotBeSerialized, navProperty.Type.FullName(), typeof(ODataMediaTypeFormatter).Name);
                        }

                        ODataSerializerWriteContext childWriteContext = new ODataSerializerWriteContext(writeContext.ResponseContext);
                        childWriteContext.UrlHelper             = writeContext.UrlHelper;
                        childWriteContext.EntitySet             = currentEntitySet;
                        childWriteContext.RootProjectionNode    = writeContext.RootProjectionNode;
                        childWriteContext.CurrentProjectionNode = expandNode;

                        serializer.WriteObjectInline(propertyValue, writer, childWriteContext);
                        writer.WriteEnd();
                    }
                    else if (!writeContext.IsRequest)
                    {
                        // delayed links cannot be written on requests
                        writer.WriteStart(navigationLink);
                        writer.WriteEnd();
                    }
                }
            }
        }
        // Build the projection tree given a select and expand and the entity set.
        // TODO: Bug 467621: replace this with the ODataUriParser functionality
        public static ODataQueryProjectionNode GetODataQueryProjectionNode(string selectQuery, string expandQuery, IEdmEntitySet entitySet)
        {
            IEnumerable<string> selects = (selectQuery ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim());
            IEnumerable<string> expands = (expandQuery ?? String.Empty).Split(new[] { ',', }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim());

            ODataQueryProjectionNode rootProjectionNode = new ODataQueryProjectionNode { Name = String.Empty, NodeType = entitySet.ElementType };

            foreach (string expand in expands)
            {
                ODataQueryProjectionNode currentProjectionNode = rootProjectionNode;

                IEnumerable<string> expandPath = expand.Split('/');
                foreach (string property in expandPath)
                {
                    ODataQueryProjectionNode nextNode = currentProjectionNode.Expands.SingleOrDefault(node => node.Name == property);
                    if (nextNode == null)
                    {
                        nextNode = new ODataQueryProjectionNode { Name = property, NodeType = (currentProjectionNode.NodeType as IEdmEntityType).Properties().SingleOrDefault(p => p.Name == property).Type.Definition };
                        currentProjectionNode.Expands.Add(nextNode);
                    }

                    currentProjectionNode = nextNode;
                }
            }

            foreach (string select in selects)
            {
                ODataQueryProjectionNode currentProjectionNode = rootProjectionNode;

                IEnumerable<string> selectPath = select.Split('/');
                foreach (string property in selectPath)
                {
                    ODataQueryProjectionNode nextNode = currentProjectionNode.Expands.SingleOrDefault(node => node.Name == property);
                    if (nextNode == null)
                    {
                        nextNode = new ODataQueryProjectionNode { Name = property, NodeType = (currentProjectionNode.NodeType as IEdmEntityType).Properties().SingleOrDefault(p => p.Name == property).Type.Definition };
                        currentProjectionNode.Selects.Add(nextNode);
                    }

                    currentProjectionNode = nextNode;
                }
            }

            return rootProjectionNode;
        }
        public void WriteObjectInline_Respects_DollarExpandAndSelect()
        {
            // Arrange
            bool order1Written = false;
            bool order2Written = false;
            bool customerWritten = false;
            Mock<ODataWriter> writer = new Mock<ODataWriter>();
            writer
                .Setup(w => w.WriteStart(It.IsAny<ODataEntry>()))
                .Callback((ODataEntry entry) =>
                {
                    if (entry.TypeName == "Default.Order")
                    {
                        string id = (string)entry.Properties.Single().Value;
                        if (id == "1")
                        {
                            order1Written = true;
                        }
                        else if (id == "2")
                        {
                            order2Written = true;
                        }
                        else
                        {
                            Assert.True(false);
                        }
                    }
                    else if (entry.TypeName == "Default.Customer")
                    {
                        Assert.Equal("FirstName", entry.Properties.Single().Name);
                        customerWritten = true;
                    }
                });

            ODataQueryProjectionNode rootNode = new ODataQueryProjectionNode
            {
                Name = "",
                NodeType = _customerSet.ElementType,
                Expands =
                {
                    new ODataQueryProjectionNode
                    {
                        NodeType = _model.FindDeclaredType("Default.Order"),
                        Name = "Orders",
                        Selects = 
                        {
                            new ODataQueryProjectionNode
                            {
                                Name = "Name",
                                NodeType = _model.FindType("Edm.String")
                            }
                        }
                    }
                },
                Selects =
                {
                    new ODataQueryProjectionNode
                    {
                        Name = "FirstName",
                        NodeType = _model.FindType("Edm.String")
                    }
                }
            };
            _customer.Orders.Add(new Order { ID = 1, Name = "1" });
            _customer.Orders.Add(new Order { ID = 2, Name = "2" });
            _writeContext.CurrentProjectionNode = rootNode;
            _writeContext.RootProjectionNode = rootNode;

            // Act
            _serializer.WriteObjectInline(_customer, writer.Object, _writeContext);

            // Assert
            Assert.True(order1Written);
            Assert.True(order2Written);
            Assert.True(customerWritten);
        }
        public void WriteObjectInline_Respects_DollarSelect()
        {
            // Arrange
            Mock<ODataWriter> writer = new Mock<ODataWriter>();
            writer
                .Setup(w => w.WriteStart(It.IsAny<ODataEntry>()))
                .Callback((ODataEntry entry) =>
                {
                    Assert.Equal("ID", entry.Properties.Single().Name);
                });

            // Act
            ODataQueryProjectionNode rootNode = new ODataQueryProjectionNode
            {
                Name = "",
                NodeType = _customerSet.ElementType,
                Selects = 
                { 
                    new ODataQueryProjectionNode
                    {
                        Name = "ID",
                        NodeType = _model.FindType("Edm.Int32")
                    }
                }
            };
            _writeContext.CurrentProjectionNode = rootNode;
            _writeContext.RootProjectionNode = rootNode;
            _serializer.WriteObjectInline(_customer, writer.Object, _writeContext);
        }