/// <summary> /// Read the normal resource. /// </summary> /// <param name="reader">The OData reader.</param> /// <param name="itemsStack">The item stack.</param> /// <param name="topLevelItem">the top level item.</param> private static void ReadResource(ODataReader reader, Stack <ODataItemWrapper> itemsStack, ref ODataItemWrapper topLevelItem) { Contract.Assert(reader != null); Contract.Assert(itemsStack != null); Contract.Assert(ODataReaderState.ResourceStart == reader.State); 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 { ODataItemWrapper parentItem = itemsStack.Peek(); ODataResourceSetWrapper parentResourceSet = parentItem as ODataResourceSetWrapper; ODataDeltaResourceSetWrapper parentDeletaResourceSet = parentItem as ODataDeltaResourceSetWrapper; if (parentResourceSet != null) { parentResourceSet.Resources.Add(resourceWrapper); } else if (parentDeletaResourceSet != null) { // Delta resource set could have the normal resource parentDeletaResourceSet.DeltaItems.Add(resourceWrapper); } else { ODataNestedResourceInfoWrapper parentNestedResource = (ODataNestedResourceInfoWrapper)parentItem; 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); } } itemsStack.Push(resourceWrapper); }
/// <summary> /// Reads a <see cref="ODataResource"/> or <see cref="ODataResourceSet"/> object. /// </summary> /// <param name="reader">The OData reader to read from.</param> /// <returns>The read resource or resource set.</returns> public static async Task <ODataItemWrapper> ReadResourceOrResourceSetAsync(this ODataReader reader) { if (reader == null) { throw Error.ArgumentNull(nameof(reader)); } ODataItemWrapper topLevelItem = null; Stack <ODataItemWrapper> itemsStack = new Stack <ODataItemWrapper>(); while (await reader.ReadAsync().ConfigureAwait(false)) { ReadODataItem(reader, itemsStack, ref topLevelItem); } Contract.Assert(reader.State == ODataReaderState.Completed, "We should have consumed all of the input by now."); Contract.Assert(topLevelItem != null, "A top level resource or resource set should have been read by now."); return(topLevelItem); }
public async Task ReadSingleEntityReferenceLinkWorksAsExpected(ODataVersion version, string referenceLink) { // Arrange string payload = "{" + // -> ResourceStart "\"@odata.context\":\"http://localhost/$metadata#Customers/$entity\"," + "\"CustomerID\": 7," + referenceLink + "}"; IEdmEntitySet customers = Model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(customers); // Guard // Act Func <ODataMessageReader, Task <ODataReader> > func = mr => mr.CreateODataResourceReaderAsync(customers, customers.EntityType()); ODataItemWrapper item = await ReadPayloadAsync(payload, Model, func, version); // Assert Assert.NotNull(item); ODataResourceWrapper resource = Assert.IsType <ODataResourceWrapper>(item); ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(resource.NestedResourceInfos); Assert.Equal("Order", nestedResourceInfo.NestedResourceInfo.Name); if (version == ODataVersion.V401) { // --- Resource // |--- NestedResourceInfo (Order) // |--- Resource ODataResourceWrapper order = Assert.IsType <ODataResourceWrapper>(nestedResourceInfo.NestedResource); Assert.Equal("http://svc/Orders(8)", order.Resource.Id.OriginalString); Assert.Empty(order.Resource.Properties); } else { // --- Resource // |--- NestedResourceInfo (Order) // |--- EntityReferenceLink ODataEntityReferenceLinkWrapper orderLink = Assert.IsType <ODataEntityReferenceLinkWrapper>(Assert.Single(nestedResourceInfo.NestedLinks)); Assert.Equal("http://svc/Orders(7)", orderLink.EntityReferenceLink.Url.OriginalString); } }
/// <summary> /// Read OData item. /// </summary> /// <param name="reader">The odata reader.</param> /// <param name="itemsStack">The item stack.</param> /// <param name="topLevelItem">The top level item.</param> private static void ReadODataItem(ODataReader reader, Stack <ODataItemWrapper> itemsStack, ref ODataItemWrapper topLevelItem) { Contract.Assert(reader != null); Contract.Assert(itemsStack != null); switch (reader.State) { case ODataReaderState.ResourceStart: ReadResource(reader, itemsStack, ref topLevelItem); break; case ODataReaderState.DeletedResourceStart: ReadDeletedResource(reader, itemsStack); break; case ODataReaderState.ResourceEnd: Contract.Assert(itemsStack.Count > 0, "The resource which is ending should be on the top of the items stack."); ODataResourceWrapper resourceWrapper = itemsStack.Peek() as ODataResourceWrapper; if (resourceWrapper != null) { // Resource could be null Contract.Assert(resourceWrapper.Resource == reader.Item, "The resource should be the same item in the reader."); } itemsStack.Pop(); break; case ODataReaderState.DeletedResourceEnd: Contract.Assert(itemsStack.Count > 0, "The deleted resource which is ending should be on the top of the items stack."); ODataResourceWrapper deletedResourceWrapper = itemsStack.Peek() as ODataResourceWrapper; Contract.Assert(deletedResourceWrapper != null, "The top object in the stack should be delete resource wrapper."); Contract.Assert(deletedResourceWrapper.Resource == reader.Item, "The deleted resource should be the same item in the reader."); 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, "The nested resource info which is ending should be on the top of the items stack."); ODataNestedResourceInfoWrapper nestedInfoWrapper = itemsStack.Peek() as ODataNestedResourceInfoWrapper; Contract.Assert(nestedInfoWrapper != null, "The top object in the stack should be nested resource info wrapper."); Contract.Assert(nestedInfoWrapper.NestedResourceInfo == reader.Item, "The nested resource info should be the same item in the reader."); itemsStack.Pop(); break; case ODataReaderState.ResourceSetStart: // resource set ReadResourceSet(reader, itemsStack, ref topLevelItem); break; case ODataReaderState.DeltaResourceSetStart: // delta resource set ReadDeltaResourceSet(reader, itemsStack, ref topLevelItem); break; case ODataReaderState.ResourceSetEnd: Contract.Assert(itemsStack.Count > 0, "The resource set which is ending should be on the top of the items stack."); ODataResourceSetWrapper resourceSetWrapper = itemsStack.Peek() as ODataResourceSetWrapper; Contract.Assert(resourceSetWrapper != null, "The top object in the stack should be resource set wrapper."); Contract.Assert(resourceSetWrapper.ResourceSet == reader.Item, "The resource set should be the same item in the reader."); itemsStack.Pop(); break; case ODataReaderState.DeltaResourceSetEnd: Contract.Assert(itemsStack.Count > 0, "The delta resource set which is ending should be on the top of the items stack."); ODataDeltaResourceSetWrapper deltaResourceSetWrapper = itemsStack.Peek() as ODataDeltaResourceSetWrapper; Contract.Assert(deltaResourceSetWrapper != null, "The top object in the stack should be delta resource set wrapper."); Contract.Assert(deltaResourceSetWrapper.DeltaResourceSet == reader.Item, "The delta resource set should be the same item in the reader."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item; Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null."); ODataEntityReferenceLinkWrapper entityReferenceLinkWrapper = new ODataEntityReferenceLinkWrapper(entityReferenceLink); Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNestedResourceInfoWrapper parentNestedResource = (ODataNestedResourceInfoWrapper)itemsStack.Peek(); parentNestedResource.NestedItems.Add(entityReferenceLinkWrapper); } break; case ODataReaderState.DeltaLink: // added link case ODataReaderState.DeltaDeletedLink: // deleted link ODataDeltaLinkBaseWrapper linkBaseWrapper; if (ODataReaderState.DeltaLink == reader.State) { ODataDeltaLink deltaLink = (ODataDeltaLink)reader.Item; Contract.Assert(deltaLink != null, "Delta link should never be null."); linkBaseWrapper = new ODataDeltaLinkWrapper(deltaLink); } else { ODataDeltaDeletedLink deltaDeletedLink = (ODataDeltaDeletedLink)reader.Item; Contract.Assert(deltaDeletedLink != null, "Delta deleted link should never be null."); linkBaseWrapper = new ODataDeltaDeletedLinkWrapper(deltaDeletedLink); } Contract.Assert(itemsStack.Count > 0, "Delta link should never be reported as top-level item."); // Should never add a delta link to a non-delta resource set. ODataDeltaResourceSetWrapper linkResourceSetWrapper = (ODataDeltaResourceSetWrapper)itemsStack.Peek(); Contract.Assert(linkResourceSetWrapper != null, "ODataDeltaResourceSetWrapper for delta link should not be null."); linkResourceSetWrapper.DeltaItems.Add(linkBaseWrapper); break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } }
/// <summary> /// Read the delta resource set. /// </summary> /// <param name="reader">The OData reader.</param> /// <param name="itemsStack">The item stack.</param> /// <param name="topLevelItem">The top level item.</param> private static void ReadDeltaResourceSet(ODataReader reader, Stack <ODataItemWrapper> itemsStack, ref ODataItemWrapper topLevelItem) { Contract.Assert(reader != null); Contract.Assert(itemsStack != null); Contract.Assert(ODataReaderState.DeltaResourceSetStart == reader.State); ODataDeltaResourceSet deltaResourceSet = (ODataDeltaResourceSet)reader.Item; Contract.Assert(deltaResourceSet != null, "Delta 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 delta resource set. inner delta resource sets always have a nested resource info."); Contract.Assert(parentNestedResourceInfo.NestedResourceInfo.IsCollection == true, "Only collection nested properties can contain delta resource set as their child."); Contract.Assert(parentNestedResourceInfo.NestedItems.Count == 0, "Each nested property can contain only one delta resource set as its direct child."); parentNestedResourceInfo.NestedItems.Add(deltaResourceSetWrapper); } else { topLevelItem = deltaResourceSetWrapper; } itemsStack.Push(deltaResourceSetWrapper); }
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) // |--- Resource (2) // |--- DeletedResource (1) // | // |--- DeltaDeletedLink // |--- DeltaLink ODataDeltaResourceSetWrapper deltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(item); // Resources Assert.Equal(3, deltaResourceSet.ResourceBases.Count); Assert.Collection(deltaResourceSet.ResourceBases, e => { 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 => { 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 => { ODataDeletedResourceWrapper deletedResource = Assert.IsType <ODataDeletedResourceWrapper>(e); Assert.Equal("Customers(21)", deletedResource.DeletedResource.Id.OriginalString); Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource.DeletedResource.Reason); }); // DeltaLinks Assert.Equal(2, deltaResourceSet.DeltaLinks.Count); Assert.Collection(deltaResourceSet.DeltaLinks, e => { 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 => { 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); }); }
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); ODataResourceBaseWrapper resourceBase = Assert.Single(deltaResourceSet.ResourceBases); ODataDeletedResourceWrapper deletedResource = Assert.IsType <ODataDeletedResourceWrapper>(resourceBase); Assert.Equal(DeltaDeletedEntryReason.Changed, deletedResource.DeletedResource.Reason); ODataNestedResourceInfoWrapper nestedResourceInfo = Assert.Single(deletedResource.NestedResourceInfos); Assert.Equal("Orders", nestedResourceInfo.NestedResourceInfo.Name); Assert.True(nestedResourceInfo.NestedResourceInfo.IsCollection); ODataDeltaResourceSetWrapper ordersDeltaResourceSet = Assert.IsType <ODataDeltaResourceSetWrapper>(nestedResourceInfo.NestedResourceSet); Assert.Equal(2, ordersDeltaResourceSet.ResourceBases.Count); ODataDeletedResourceWrapper deletedResource1 = Assert.IsType <ODataDeletedResourceWrapper>(ordersDeltaResourceSet.ResourceBases.ElementAt(0)); Assert.Equal(DeltaDeletedEntryReason.Deleted, deletedResource1.DeletedResource.Reason); ODataResourceWrapper resource2 = Assert.IsType <ODataResourceWrapper>(ordersDeltaResourceSet.ResourceBases.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); }); }
/// <summary> /// Tries to convert the given value into an instance of <see cref="ODataItemWrapper"/>. /// </summary> /// <param name="property">The property being converted.</param> /// <param name="propertyValue">The property value to convert..</param> /// <param name="serverTypeName">The server type name of the entity whose properties are being populated.</param> /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param> /// <param name="odataItem">The odata resource or resource set if one was created.</param> /// <returns>Whether or not the value was converted.</returns> private bool TryConvertPropertyToResourceOrResourceSet(ClientPropertyAnnotation property, object propertyValue, string serverTypeName, HashSet <object> visitedComplexTypeObjects, out ODataItemWrapper odataItem) { if (property.IsComplexCollection) { odataItem = this.CreateODataComplexCollectionPropertyResourceSet(property, propertyValue, serverTypeName, visitedComplexTypeObjects); return(true); } if (property.IsComplex) { odataItem = this.CreateODataComplexPropertyResource(property, propertyValue, visitedComplexTypeObjects); return(true); } odataItem = null; return(false); }
public static void TestReadResource() { string requestData = @"{ ""@odata.type"": ""#NS.Customer"", ""*****@*****.**"": ""Cloud"", ""DisplayName"": ""Group Display Name"", ""*****@*****.**"": ""Cloud"", ""AssignedLabels"": [ { ""City"": ""City1"", ""Street"": ""Street1"" } ] }"; Dictionary <string, string> headers = new Dictionary <string, string>(); headers.Add("Content-Type", "application/json;odata.metadata=minima;odata.streaming=true"); headers.Add("Accept", "application/json"); ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings { BaseUri = new Uri("http://localhost"), ShouldIncludeAnnotation = s => true }; //ODataResourceWrapper topLevelResource = null; ODataItemWrapper topLevel = null, currentItem = null; IEdmModel model = EdmModelBuilder.GetEdmModel(); IEdmEntitySet customers = model.EntityContainer.FindEntitySet("Customers"); // ODataResource resource = null; using (MemoryStream ms = new MemoryStream(Encoding.GetEncoding("iso-8859-1").GetBytes(requestData))) { ODataMessageWrapper requestMessage = new ODataMessageWrapper(ms); ODataMessageReader messageReader = new ODataMessageReader((IODataRequestMessage)requestMessage, readerSettings, model); Stack <ODataItemWrapper> resStack = new Stack <ODataItemWrapper>(); ODataReader odataReader = messageReader.CreateODataResourceReader(customers, customers.EntityType()); while (odataReader.Read()) { Console.WriteLine(odataReader.State); switch (odataReader.State) { case ODataReaderState.ResourceStart: ODataResourceWrapper newResource = new ODataResourceWrapper(); newResource.Resource = odataReader.Item as ODataResource; resStack.TryPeek(out currentItem); if (currentItem == null) { // TopLevel, do nothing Debug.Assert(topLevel == null); topLevel = newResource; } else { currentItem.Append(newResource); } resStack.Push(newResource); break; case ODataReaderState.ResourceSetStart: ODataResourceSet resourceSet = (ODataResourceSet)odataReader.Item; ODataResourceSetWrapper setWrapper = new ODataResourceSetWrapper { ResourceSet = resourceSet }; resStack.TryPeek(out currentItem); if (currentItem == null) { // TopLevel, do nothing Debug.Assert(topLevel == null); topLevel = setWrapper; } else { currentItem.Append(setWrapper); } resStack.Push(setWrapper); break; case ODataReaderState.NestedResourceInfoStart: resStack.TryPeek(out currentItem); Debug.Assert(currentItem != null); ODataItem item = odataReader.Item; ODataNestedResourceInfoWrapper infoWrapper = new ODataNestedResourceInfoWrapper { NestedInfo = item as ODataNestedResourceInfo }; currentItem.Append(infoWrapper); resStack.Push(infoWrapper); break; case ODataReaderState.ResourceEnd: //currWrapper = resStack.Peek(); //currWrapper.Resource = (ODataResource)odataReader.Item; resStack.Pop(); break; case ODataReaderState.ResourceSetEnd: resStack.Pop(); break; case ODataReaderState.NestedResourceInfoEnd: item = odataReader.Item; resStack.Pop(); break; } } } if (topLevel == null) { return; } ODataResourceWrapper topLevelResource = topLevel as ODataResourceWrapper; if (topLevelResource != null) { foreach (var a in topLevelResource.Resource.Properties) { Console.WriteLine(a.Name + ": " + a.Value); } foreach (var a in topLevelResource.NestedResourceInfos) { Console.WriteLine(a.NestedInfo.Name); ODataResourceSetWrapper setWrapper = a.NestedWrapper as ODataResourceSetWrapper; ODataResourceWrapper resourceWrapper = a.NestedWrapper as ODataResourceWrapper; if (resourceWrapper != null) { foreach (var prop in resourceWrapper.Resource.Properties) { Console.WriteLine(prop.Name + ": " + prop.Value); } } } } }
/// <summary> /// Read the resource set. /// </summary> /// <param name="reader">The OData reader.</param> /// <param name="itemsStack">The item stack.</param> /// <param name="topLevelItem">The top level item.</param> private static void ReadResourceSet(ODataReader reader, Stack <ODataItemWrapper> itemsStack, ref ODataItemWrapper topLevelItem) { Contract.Assert(reader != null); Contract.Assert(itemsStack != null); Contract.Assert(ODataReaderState.ResourceSetStart == reader.State); 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."); Contract.Assert(parentNestedResourceInfo.NestedLinks == null, "collection single nested property can not contain reference link as its direct child."); Contract.Assert(parentNestedResourceInfo.NestedResource == null, "collection nested properties can not contain other resource as their child."); Contract.Assert(parentNestedResourceInfo.NestedResourceSet == null, "collection nested properties can not contain multiple resource set as their child."); parentNestedResourceInfo.NestedResourceSet = resourceSetWrapper; } else { topLevelItem = resourceSetWrapper; } itemsStack.Push(resourceSetWrapper); }