/// <summary>
        /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
        /// messageWriter and the writeContext.
        /// </summary>
        /// <param name="graph">The object to be written.</param>
        /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
        /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
        public virtual async Task WriteDeltaDeletedEntryAsync(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            if (writer == null)
            {
                throw Error.ArgumentNull(nameof(writer));
            }

            EdmDeltaDeletedEntityObject edmDeltaDeletedEntity = graph as EdmDeltaDeletedEntityObject;

            if (edmDeltaDeletedEntity == null)
            {
                throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph?.GetType().FullName));
            }

            Uri id = StringToUri(edmDeltaDeletedEntity.Id);
            ODataDeletedResource deletedResource = new ODataDeletedResource(id, edmDeltaDeletedEntity.Reason);

            if (edmDeltaDeletedEntity.NavigationSource != null)
            {
                ODataResourceSerializationInfo serializationInfo = new ODataResourceSerializationInfo
                {
                    NavigationSourceName = edmDeltaDeletedEntity.NavigationSource.Name
                };
                deletedResource.SetSerializationInfo(serializationInfo);
            }

            if (deletedResource != null)
            {
                await writer.WriteStartAsync(deletedResource).ConfigureAwait(false);

                await writer.WriteEndAsync().ConfigureAwait(false);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
        /// messageWriter and the writeContext.
        /// </summary>
        /// <param name="graph">The object to be written.</param>
        /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
        /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
        public virtual void WriteDeltaDeletedEntry(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            EdmDeltaDeletedEntityObject edmDeltaDeletedEntity = graph as EdmDeltaDeletedEntityObject;

            if (edmDeltaDeletedEntity == null)
            {
                throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName));
            }

            Uri id = StringToUri(edmDeltaDeletedEntity.Id);
            ODataDeletedResource deletedResource = new ODataDeletedResource(id, edmDeltaDeletedEntity.Reason);

            if (edmDeltaDeletedEntity.NavigationSource != null)
            {
                ODataResourceSerializationInfo serializationInfo = new ODataResourceSerializationInfo
                {
                    NavigationSourceName = edmDeltaDeletedEntity.NavigationSource.Name
                };
                deletedResource.SetSerializationInfo(serializationInfo);
            }

            if (deletedResource != null)
            {
                writer.WriteStart(deletedResource);
                writer.WriteEnd();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Read the deleted resource.
        /// </summary>
        /// <param name="reader">The OData reader.</param>
        /// <param name="itemsStack">The item stack.</param>
        private static void ReadDeletedResource(ODataReader reader, Stack <ODataItemWrapper> itemsStack)
        {
            Contract.Assert(reader != null);
            Contract.Assert(itemsStack != null);
            Contract.Assert(ODataReaderState.DeletedResourceStart == reader.State);

            ODataDeletedResource deletedResource = (ODataDeletedResource)reader.Item;

            Contract.Assert(deletedResource != null, "Deleted resource should not be null");

            ODataResourceWrapper deletedResourceWrapper = new ODataResourceWrapper(deletedResource);

            // top-level resource should never be deleted.
            Contract.Assert(itemsStack.Count != 0, "Deleted Resource should not be top level item");

            ODataItemWrapper             parentItem = itemsStack.Peek();
            ODataDeltaResourceSetWrapper parentDeletaResourceSet = parentItem as ODataDeltaResourceSetWrapper;

            if (parentDeletaResourceSet != null)
            {
                parentDeletaResourceSet.DeltaItems.Add(deletedResourceWrapper);
            }
            else
            {
                ODataNestedResourceInfoWrapper parentNestedResource = (ODataNestedResourceInfoWrapper)itemsStack.Peek();
                Contract.Assert(parentNestedResource.NestedResourceInfo.IsCollection == false, "Only singleton nested properties can contain resource as their child.");
                Contract.Assert(parentNestedResource.NestedItems.Count == 0, "Each nested property can contain only one deleted resource as its direct child.");
                parentNestedResource.NestedItems.Add(deletedResourceWrapper);
            }

            itemsStack.Push(deletedResourceWrapper);
        }
Exemplo n.º 4
0
        public async Task ReadDeletedLinkInDeltaResourceSetWorksAsExpected2()
        {
            // Arrange
            string payload = "{\"@context\":\"http://example.com/$metadata#Customers/$delta\"," +
                             "\"value\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"changed\"}," +
                             "\"CustomerID\":1," +
                             "\"Order@delta\":{" +
                             "\"@context\":\"#Orders/$deletedEntity\"," +
                             "\"@removed\":{\"reason\":\"deleted\"}," +
                             "\"OrderId\":10" +
                             "}" +
                             "}" +
                             "]" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func, ODataVersion.V401);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- DeleteResource (Changed)
            //         |--- NestedResourceInfo
            //            |--- DeleteResource (Deleted)
            ODataDeltaResourceSetWrapper deltaResourceSet       = Assert.IsType <ODataDeltaResourceSetWrapper>(item);
            ODataItemWrapper             deltaItem              = Assert.Single(deltaResourceSet.DeltaItems);
            ODataResourceWrapper         deletedResourceWrapper = Assert.IsType <ODataResourceWrapper>(deltaItem);
            ODataDeletedResource         deletedResource        = Assert.IsType <ODataDeletedResource>(deletedResourceWrapper.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Changed, deletedResource.Reason);

            ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(deletedResourceWrapper.NestedResourceInfos);

            Assert.Equal("Order", nestedResourceInfo.NestedResourceInfo.Name);
            Assert.False(nestedResourceInfo.NestedResourceInfo.IsCollection);

            ODataItemWrapper     nestedItem    = Assert.Single(nestedResourceInfo.NestedItems);
            ODataResourceWrapper orderResource = Assert.IsType <ODataResourceWrapper>(nestedItem);

            Assert.True(orderResource.IsDeletedResource);
            ODataDeletedResource innerDeletedResource = Assert.IsType <ODataDeletedResource>(orderResource.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Deleted, innerDeletedResource.Reason);

            ODataProperty property = Assert.Single(innerDeletedResource.Properties);

            Assert.Equal("OrderId", property.Name);
            Assert.Equal(10, property.Value);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
        /// messageWriter and the writeContext.
        /// </summary>
        /// <param name="graph">The object to be written.</param>
        /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
        /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
        public virtual void WriteDeltaDeletedEntry(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            ODataDeletedResource deletedResource = GetDeletedResource(graph);

            if (deletedResource != null)
            {
                writer.WriteStart(deletedResource);
                writer.WriteEnd();
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
        /// messageWriter and the writeContext.
        /// </summary>
        /// <param name="graph">The object to be written.</param>
        /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
        /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
        public virtual async Task WriteDeltaDeletedEntryAsync(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            ODataDeletedResource deletedResource = GetDeletedResource(graph);

            if (deletedResource != null)
            {
                await writer.WriteStartAsync(deletedResource);

                await writer.WriteEndAsync();
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
        /// messageWriter and the writeContext.
        /// </summary>
        /// <param name="value">The object to be written.</param>
        /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
        /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
        public virtual async Task WriteDeltaDeletedResourceAsync(object value, ODataWriter writer, ODataSerializerContext writeContext)
        {
            if (writer == null)
            {
                throw Error.ArgumentNull(nameof(writer));
            }

            ODataDeletedResource odataDeletedResource;

            if (value is EdmDeltaDeletedResourceObject edmDeltaDeletedEntity)
            {
                odataDeletedResource = new ODataDeletedResource(edmDeltaDeletedEntity.Id, edmDeltaDeletedEntity.Reason ?? DeltaDeletedEntryReason.Deleted);

                if (edmDeltaDeletedEntity.NavigationSource != null)
                {
                    ODataResourceSerializationInfo serializationInfo = new ODataResourceSerializationInfo
                    {
                        NavigationSourceName = edmDeltaDeletedEntity.NavigationSource.Name
                    };
                    odataDeletedResource.SetSerializationInfo(serializationInfo);
                }
            }
            else if (value is IDeltaDeletedResource deltaDeletedResource)
            {
                odataDeletedResource = new ODataDeletedResource(deltaDeletedResource.Id, deltaDeletedResource.Reason ?? DeltaDeletedEntryReason.Deleted);
            }
            else
            {
                throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, value?.GetType().FullName));
            }

            if (odataDeletedResource != null)
            {
                await writer.WriteStartAsync(odataDeletedResource).ConfigureAwait(false);

                await writer.WriteEndAsync().ConfigureAwait(false);
            }
        }
Exemplo n.º 8
0
        private ODataDeletedResource GetDeletedResource(object graph)
        {
            EdmDeltaDeletedEntityObject edmDeltaDeletedEntity = graph as EdmDeltaDeletedEntityObject;

            if (edmDeltaDeletedEntity == null)
            {
                throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName));
            }

            Uri id = StringToUri(edmDeltaDeletedEntity.Id);
            ODataDeletedResource deletedResource = new ODataDeletedResource(id, edmDeltaDeletedEntity.Reason);

            if (edmDeltaDeletedEntity.NavigationSource != null)
            {
                ODataResourceSerializationInfo serializationInfo = new ODataResourceSerializationInfo
                {
                    NavigationSourceName = edmDeltaDeletedEntity.NavigationSource.Name
                };
                deletedResource.SetSerializationInfo(serializationInfo);
            }

            return(deletedResource);
        }
Exemplo n.º 9
0
        public void ReadDeltaResource_Returns_DeletedResource(bool typed)
        {
            // Arrange
            IEdmModel      model    = GetEdmModel();
            IEdmEntityType customer = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer");
            IEdmStructuredTypeReference elementType = new EdmEntityTypeReference(customer, true);

            Mock <IODataDeserializerProvider> deserializerProvider = new Mock <IODataDeserializerProvider>();
            ODataResourceDeserializer         resourceDeserializer = new ODataResourceDeserializer(deserializerProvider.Object);

            Uri id = new Uri("Customers(8)", UriKind.RelativeOrAbsolute);
            ODataDeletedResource customerDeleted = new ODataDeletedResource(id, DeltaDeletedEntryReason.Deleted)
            {
                Properties = new List <ODataProperty>
                {
                    new ODataProperty {
                        Name = "FirstName", Value = "Peter"
                    },
                    new ODataProperty {
                        Name = "LastName", Value = "John"
                    }
                }
            };
            ODataResourceWrapper     resourceWrapper = new ODataResourceWrapper(customerDeleted);
            ODataDeserializerContext context         = new ODataDeserializerContext
            {
                Model = model,
            };

            if (typed)
            {
                context.ResourceType = typeof(DeltaSet <>);
            }
            else
            {
                context.ResourceType = typeof(EdmChangedObjectCollection);
            }

            deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny <IEdmTypeReference>(), false)).Returns(resourceDeserializer);
            ODataDeltaResourceSetDeserializer deserializer = new ODataDeltaResourceSetDeserializer(deserializerProvider.Object);

            // Act
            object result = deserializer.ReadDeltaResource(resourceWrapper, elementType, context);

            // Assert
            Action <Delta> testPropertyAction = d =>
            {
                d.TryGetPropertyValue("FirstName", out object firstName);
                Assert.Equal("Peter", firstName);
                d.TryGetPropertyValue("LastName", out object lastName);
                Assert.Equal("John", lastName);
            };

            if (typed)
            {
                DeltaDeletedResource <Customer> deltaDeletedResource = Assert.IsType <DeltaDeletedResource <Customer> >(result);
                Assert.Equal(id, deltaDeletedResource.Id);
                Assert.Equal(DeltaDeletedEntryReason.Deleted, deltaDeletedResource.Reason);
                testPropertyAction(deltaDeletedResource);
            }
            else
            {
                EdmDeltaDeletedResourceObject deltaDeletedResource = Assert.IsType <EdmDeltaDeletedResourceObject>(result);
                Assert.Equal(id, deltaDeletedResource.Id);
                Assert.Equal(DeltaDeletedEntryReason.Deleted, deltaDeletedResource.Reason);
                testPropertyAction(deltaDeletedResource);
            }
        }
Exemplo n.º 10
0
        public async Task ReadDeletedLinkInDeltaResourceSetWorksAsExpected()
        {
            // Arrange
            string payload = "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$delta\"," +
                             "\"@odata.count\":5," +
                             "\"value\":[" +
                             "{" +
                             "\"@odata.id\":\"Customers(42)\"," +
                             "\"Name\":\"Sammy\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$deletedLink\"," +
                             "\"source\":\"Customers(39)\"," +
                             "\"relationship\":\"Orders\"," +
                             "\"target\":\"Orders(10643)\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$link\"," +
                             "\"source\":\"Customers(32)\"," +
                             "\"relationship\":\"Orders\"," +
                             "\"target\":\"Orders(10645)\"" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Orders/$entity\"," +
                             "\"@odata.id\":\"Orders(10643)\"," +
                             "\"Price\": 82" +
                             "}," +
                             "{" +
                             "\"@odata.context\":\"http://localhost/$metadata#Customers/$deletedEntity\"," +
                             "\"id\":\"Customers(21)\"," +
                             "\"reason\":\"deleted\"" +
                             "}" +
                             "]," +
                             "\"@odata.deltaLink\":\"Customers?$expand=Orders&$deltatoken=8015\"" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- Resource (1)
            //      |--- DeltaDeletedLink
            //      |--- DeltaLink
            //      |--- Resource (2)
            //      |--- DeletedResource (1)
            //      |
            ODataDeltaResourceSetWrapper deltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(item);

            // Resources
            Assert.Equal(5, deltaResourceSet.DeltaItems.Count);
            Assert.Collection(deltaResourceSet.DeltaItems,
                              e =>
            {
                // 1) Resource
                ODataResourceWrapper resource1 = Assert.IsType <ODataResourceWrapper>(e);
                Assert.Equal("Customers(42)", resource1.Resource.Id.OriginalString);
                Assert.Equal("Sammy", resource1.Resource.Properties.First(p => p.Name == "Name").Value);
            },
                              e =>
            {
                // 2) Deleted Link
                ODataDeltaDeletedLinkWrapper deletedLinkWrapper = Assert.IsType <ODataDeltaDeletedLinkWrapper>(e);
                Assert.Equal("Customers(39)", deletedLinkWrapper.DeltaDeletedLink.Source.OriginalString);
                Assert.Equal("Orders(10643)", deletedLinkWrapper.DeltaDeletedLink.Target.OriginalString);
                Assert.Equal("Orders", deletedLinkWrapper.DeltaDeletedLink.Relationship);
            },
                              e =>
            {
                // 3) Added Link
                ODataDeltaLinkWrapper linkWrapper = Assert.IsType <ODataDeltaLinkWrapper>(e);
                Assert.Equal("Customers(32)", linkWrapper.DeltaLink.Source.OriginalString);
                Assert.Equal("Orders(10645)", linkWrapper.DeltaLink.Target.OriginalString);
                Assert.Equal("Orders", linkWrapper.DeltaLink.Relationship);
            },
                              e =>
            {
                // 4) Resource
                ODataResourceWrapper resource2 = Assert.IsType <ODataResourceWrapper>(e);
                Assert.Equal("Orders(10643)", resource2.Resource.Id.OriginalString);
                Assert.Equal(82, resource2.Resource.Properties.First(p => p.Name == "Price").Value);
            },
                              e =>
            {
                // 5) Deleted resource
                ODataResourceWrapper deletedResourceWrapper = Assert.IsType <ODataResourceWrapper>(e);
                ODataDeletedResource deletedResource        = Assert.IsType <ODataDeletedResource>(deletedResourceWrapper.Resource);
                Assert.Equal("Customers(21)", deletedResource.Id.OriginalString);
                Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource.Reason);
            });
        }
Exemplo n.º 11
0
        public async Task ReadDeltaResourceSetWorksAsExpected()
        {
            // Arrange
            string payload = "{\"@context\":\"http://example.com/$metadata#Customers/$delta\"," +
                             "\"value\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"changed\"}," +
                             "\"CustomerID\":1," +
                             "\"Orders@delta\":[" +
                             "{" +
                             "\"@removed\":{\"reason\":\"deleted\"}," +
                             "\"OrderId\":10" +
                             "}," +
                             "{" +
                             "\"@type\":\"#NS.VipOrder\"," +
                             "\"OrderId\":9," +
                             "\"Email\":\"[email protected]\"" +
                             "}" +
                             "]" +
                             "}" +
                             "]" +
                             "}";

            IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers");

            Assert.NotNull(customers); // Guard

            // Act
            Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataDeltaResourceSetReaderAsync(customers, customers.EntityType());
            ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func, ODataVersion.V401);

            // Assert
            Assert.NotNull(item);

            // --- DeltaResourceSet
            //      |--- DeleteResource (1)
            //          |--- NestedResourceInfo (1-1)
            //               |--- DeltaResourceSet
            //                     |--- DelteResource
            //                     |--- Normal Resource
            ODataDeltaResourceSetWrapper deltaResourceSet       = Assert.IsType <ODataDeltaResourceSetWrapper>(item);
            ODataItemWrapper             deltaItem              = Assert.Single(deltaResourceSet.DeltaItems);
            ODataResourceWrapper         deletedResourceWrapper = Assert.IsType <ODataResourceWrapper>(deltaItem);
            ODataDeletedResource         deletedResource        = Assert.IsType <ODataDeletedResource>(deletedResourceWrapper.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Changed, deletedResource.Reason);

            ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(deletedResourceWrapper.NestedResourceInfos);

            Assert.Equal("Orders", nestedResourceInfo.NestedResourceInfo.Name);
            Assert.True(nestedResourceInfo.NestedResourceInfo.IsCollection);

            ODataItemWrapper             nestedItem             = Assert.Single(nestedResourceInfo.NestedItems);
            ODataDeltaResourceSetWrapper ordersDeltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(nestedItem);

            Assert.Equal(2, ordersDeltaResourceSet.DeltaItems.Count);
            ODataResourceWrapper resource1        = Assert.IsType <ODataResourceWrapper>(ordersDeltaResourceSet.DeltaItems.ElementAt(0));
            ODataDeletedResource deletedResource1 = Assert.IsType <ODataDeletedResource>(resource1.Resource);

            Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource1.Reason);

            ODataResourceWrapper resource2 = Assert.IsType <ODataResourceWrapper>(ordersDeltaResourceSet.DeltaItems.ElementAt(1));

            Assert.Equal("NS.VipOrder", resource2.Resource.TypeName);
            Assert.Collection(resource2.Resource.Properties,
                              p =>
            {
                Assert.Equal("OrderId", p.Name);
                Assert.Equal(9, p.Value);
            },
                              p =>
            {
                Assert.Equal("Email", p.Name);
                Assert.Equal("*****@*****.**", p.Value);
            });
        }
Exemplo n.º 12
0
 /// <summary>
 /// Initializes a new instance of <see cref="ODataDeletedResourceWrapper"/>.
 /// </summary>
 /// <param name="item">The wrapped item.</param>
 public ODataDeletedResourceWrapper(ODataDeletedResource item)
     : base(item)
 {
 }
Exemplo n.º 13
0
 /// <summary>
 /// Initializes a new instance of <see cref="ODataDeletedResourceWrapper"/>.
 /// </summary>
 /// <param name="deletedResource">The wrapped deleted resource item.</param>
 public ODataDeletedResourceWrapper(ODataDeletedResource deletedResource)
 {
     DeletedResource = deletedResource;
 }
Exemplo n.º 14
0
        private static void ReadCollectionItem(ODataReader reader, Stack <ODataItemBase> itemsStack, ref ODataItemBase topLevelItem)
        {
            switch (reader.State)
            {
            case ODataReaderState.ResourceStart:
                ODataResource        resource        = (ODataResource)reader.Item;
                ODataResourceWrapper resourceWrapper = null;
                if (resource != null)
                {
                    resourceWrapper = new ODataResourceWrapper(resource);
                }

                if (itemsStack.Count == 0)
                {
                    Contract.Assert(resource != null, "The top-level resource can never be null.");
                    topLevelItem = resourceWrapper;
                }
                else
                {
                    ODataItemBase           parentItem        = itemsStack.Peek();
                    ODataResourceSetWrapper parentResourceSet = parentItem as ODataResourceSetWrapper;
                    if (parentResourceSet != null)
                    {
                        parentResourceSet.Resources.Add(resourceWrapper);
                    }
                    else
                    {
                        ODataNestedResourceInfoWrapper parentNestedResource = parentItem as ODataNestedResourceInfoWrapper;

                        if (parentNestedResource != null)
                        {
                            Contract.Assert(parentNestedResource.NestedResourceInfo.IsCollection == false, "Only singleton nested properties can contain resource as their child.");
                            Contract.Assert(parentNestedResource.NestedItems.Count == 0, "Each nested property can contain only one resource as its direct child.");
                            parentNestedResource.NestedItems.Add(resourceWrapper);
                        }
                        else
                        {
                            ODataDeltaResourceSetWrapper parentDeltaSetResource = (ODataDeltaResourceSetWrapper)parentItem;
                            parentDeltaSetResource.Resources.Add(resourceWrapper);
                        }
                    }
                }

                itemsStack.Push(resourceWrapper);
                break;

            case ODataReaderState.ResourceEnd:
                Contract.Assert(
                    itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item),
                    "The resource which is ending should be on the top of the items stack.");
                itemsStack.Pop();
                break;

            case ODataReaderState.NestedResourceInfoStart:
                ODataNestedResourceInfo nestedResourceInfo = (ODataNestedResourceInfo)reader.Item;
                Contract.Assert(nestedResourceInfo != null, "nested resource info should never be null.");

                ODataNestedResourceInfoWrapper nestedResourceInfoWrapper = new ODataNestedResourceInfoWrapper(nestedResourceInfo);
                Contract.Assert(itemsStack.Count > 0, "nested resource info can't appear as top-level item.");
                {
                    ODataResourceWrapper parentResource = (ODataResourceWrapper)itemsStack.Peek();
                    parentResource.NestedResourceInfos.Add(nestedResourceInfoWrapper);
                }

                itemsStack.Push(nestedResourceInfoWrapper);
                break;

            case ODataReaderState.NestedResourceInfoEnd:
                Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item,
                                "The nested resource info which is ending should be on the top of the items stack.");
                itemsStack.Pop();
                break;

            case ODataReaderState.ResourceSetStart:
                ODataResourceSet resourceSet = (ODataResourceSet)reader.Item;
                Contract.Assert(resourceSet != null, "ResourceSet should never be null.");

                ODataResourceSetWrapper resourceSetWrapper = new ODataResourceSetWrapper(resourceSet);
                if (itemsStack.Count > 0)
                {
                    ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek();
                    Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info.");
                    Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child.");
                    parentNestedResourceInfo.NestedItems.Add(resourceSetWrapper);
                }
                else
                {
                    topLevelItem = resourceSetWrapper;
                }

                itemsStack.Push(resourceSetWrapper);
                break;

            case ODataReaderState.ResourceSetEnd:
                Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set which is ending should be on the top of the items stack.");
                itemsStack.Pop();
                break;

            case ODataReaderState.EntityReferenceLink:
                ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item;
                Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null.");
                ODataEntityReferenceLinkBase entityReferenceLinkWrapper = new ODataEntityReferenceLinkBase(entityReferenceLink);

                Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item.");
                {
                    ODataNestedResourceInfoWrapper parentNavigationLink = (ODataNestedResourceInfoWrapper)itemsStack.Peek();
                    parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper);
                }

                break;

            case ODataReaderState.DeltaResourceSetStart:

                ODataDeltaResourceSet deltaResourceSet = (ODataDeltaResourceSet)reader.Item;
                Contract.Assert(deltaResourceSet != null, "ResourceSet should never be null.");

                ODataDeltaResourceSetWrapper deltaResourceSetWrapper = new ODataDeltaResourceSetWrapper(deltaResourceSet);
                if (itemsStack.Count > 0)
                {
                    ODataNestedResourceInfoWrapper parentNestedResourceInfo = (ODataNestedResourceInfoWrapper)itemsStack.Peek();
                    Contract.Assert(parentNestedResourceInfo != null, "this has to be an inner resource set. inner resource sets always have a nested resource info.");
                    Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain resource set as their child.");
                    parentNestedResourceInfo.NestedItems.Add(deltaResourceSetWrapper);
                }
                else
                {
                    topLevelItem = deltaResourceSetWrapper;
                }

                itemsStack.Push(deltaResourceSetWrapper);

                break;

            case ODataReaderState.DeltaResourceSetEnd:

                Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The resource set which is ending should be on the top of the items stack.");
                itemsStack.Pop();
                break;

            case ODataReaderState.DeletedResourceStart:
                ODataDeletedResource deletedResource = (ODataDeletedResource)reader.Item;

                if (deletedResource != null)
                {
                    // Note: I expect that deleted resourced will not have other nested resources

                    ODataDeletedResourceWrapper deletedResourceWrapper = new ODataDeletedResourceWrapper(deletedResource);
                    ODataItemBase parentItem = itemsStack.Peek();
                    ODataDeltaResourceSetWrapper parentDeltaSetResource = parentItem as ODataDeltaResourceSetWrapper;

                    if (parentDeltaSetResource != null)
                    {
                        parentDeltaSetResource.DeletedResources.Add(deletedResourceWrapper);
                    }
                }

                break;

            case ODataReaderState.DeletedResourceEnd:
                break;

            default:
                Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state.");
                break;
            }
        }