private void StartRead(ODataReader reader, ODataWriter writer) { ExceptionUtilities.Assert(reader.State == ODataReaderState.Start, "Reader is expected to be in state Start at StartRead."); while (reader.Read()) { switch(reader.State) { case ODataReaderState.EntryStart: writer.WriteStart((ODataEntry)reader.Item); break; case ODataReaderState.FeedStart: writer.WriteStart((ODataFeed)reader.Item); break; case ODataReaderState.NavigationLinkStart: writer.WriteStart((ODataNavigationLink)reader.Item); break; case ODataReaderState.EntryEnd: case ODataReaderState.FeedEnd: case ODataReaderState.NavigationLinkEnd: writer.WriteEnd(); break; default: throw new NotSupportedException(); }; } }
private ODataResponse ReadResponse(ODataReader odataReader) { ResponseNode rootNode = null; var nodeStack = new Stack<ResponseNode>(); while (odataReader.Read()) { if (odataReader.State == ODataReaderState.Completed) break; switch (odataReader.State) { case ODataReaderState.FeedStart: StartFeed(nodeStack, CreateFeedAnnotaions(odataReader.Item as ODataFeed)); break; case ODataReaderState.FeedEnd: EndFeed(nodeStack, CreateFeedAnnotaions(odataReader.Item as ODataFeed), ref rootNode); break; case ODataReaderState.EntryStart: StartEntry(nodeStack); break; case ODataReaderState.EntryEnd: EndEntry(nodeStack, ref rootNode, odataReader.Item); break; case ODataReaderState.NavigationLinkStart: StartNavigationLink(nodeStack, (odataReader.Item as ODataNavigationLink).Name); break; case ODataReaderState.NavigationLinkEnd: EndNavigationLink(nodeStack); break; } } return ODataResponse.FromNode(rootNode); }
/// <summary> /// Reads an ODataFeed or an ODataItem from the reader. /// </summary> /// <param name="reader">The OData reader to read from.</param> /// <returns>The read feed or entry.</returns> public static ODataItemBase ReadEntryOrFeed(ODataReader reader) { if (reader == null) { throw Error.ArgumentNull("odataReader"); } ODataItemBase topLevelItem = null; Stack<ODataItemBase> itemsStack = new Stack<ODataItemBase>(); while (reader.Read()) { switch (reader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)reader.Item; ODataEntryWithNavigationLinks entryWrapper = null; if (entry != null) { entryWrapper = new ODataEntryWithNavigationLinks(entry); } if (itemsStack.Count == 0) { Contract.Assert(entry != null, "The top-level entry can never be null."); topLevelItem = entryWrapper; } else { ODataItemBase parentItem = itemsStack.Peek(); ODataFeedWithEntries parentFeed = parentItem as ODataFeedWithEntries; if (parentFeed != null) { parentFeed.Entries.Add(entryWrapper); } else { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)parentItem; Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Contract.Assert(parentNavigationLink.NestedItems.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLink.NestedItems.Add(entryWrapper); } } itemsStack.Push(entryWrapper); break; case ODataReaderState.EntryEnd: Contract.Assert(itemsStack.Count > 0 && (reader.Item == null || itemsStack.Peek().Item == reader.Item), "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)reader.Item; Contract.Assert(navigationLink != null, "Navigation link should never be null."); ODataNavigationLinkWithItems navigationLinkWrapper = new ODataNavigationLinkWithItems(navigationLink); Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntryWithNavigationLinks parentEntry = (ODataEntryWithNavigationLinks)itemsStack.Peek(); parentEntry.NavigationLinks.Add(navigationLinkWrapper); } itemsStack.Push(navigationLinkWrapper); break; case ODataReaderState.NavigationLinkEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The navigation link which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.FeedStart: ODataFeed feed = (ODataFeed)reader.Item; Contract.Assert(feed != null, "Feed should never be null."); ODataFeedWithEntries feedWrapper = new ODataFeedWithEntries(feed); if (itemsStack.Count > 0) { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link."); Contract.Assert(parentNavigationLink.NavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLink.NestedItems.Add(feedWrapper); } else { topLevelItem = feedWrapper; } itemsStack.Push(feedWrapper); break; case ODataReaderState.FeedEnd: Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek().Item == reader.Item, "The feed 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."); { ODataNavigationLinkWithItems parentNavigationLink = (ODataNavigationLinkWithItems)itemsStack.Peek(); parentNavigationLink.NestedItems.Add(entityReferenceLinkWrapper); } break; default: Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Contract.Assert(reader.State == ODataReaderState.Completed, "We should have consumed all of the input by now."); Contract.Assert(topLevelItem != null, "A top level entry or feed should have been read by now."); return topLevelItem; }
public static ODataFeed ReadFeedParameterValue(ODataReader feedReader) { ODataFeed entry = null; while (feedReader.Read()) { if (feedReader.State == ODataReaderState.FeedEnd) { entry = feedReader.Item as ODataFeed; } } return entry; }
public static ODataEntry ReadEntryParameterValue(ODataReader entryReader) { ODataEntry entry = null; while (entryReader.Read()) { if (entryReader.State == ODataReaderState.EntryEnd) { entry = entryReader.Item as ODataEntry; } } return entry; }
/// <summary> /// Read a navigation link with an <see cref="ODataReader"/> positioned on the navigation link start. /// </summary> /// <param name="reader">The <see cref="ODataReader"/> to use for reading the navigation link.</param> /// <returns>An <see cref="ODataNavigationLink"/>, possibly with annotations.</returns> /// <returns></returns> private ODataNavigationLink ReadNavigationLink(ODataReader reader) { this.assert.AreEqual(ODataReaderState.NavigationLinkStart, reader.State, "Reader states don't match."); reader.Read(); List<ODataItem> expandedItems = new List<ODataItem>(); while (reader.State != ODataReaderState.NavigationLinkEnd) { if (reader.State == ODataReaderState.EntryStart) { if (reader.Item == null) { expandedItems.Add(null); // Read over the entry start reader.Read(); } else { expandedItems.Add(this.ReadEntry(reader)); } this.assert.AreEqual(ODataReaderState.EntryEnd, reader.State, "Reader states don't match."); } else if (reader.State == ODataReaderState.FeedStart) { expandedItems.Add(this.ReadFeed(reader)); this.assert.AreEqual(ODataReaderState.FeedEnd, reader.State, "Reader states don't match."); } else if (reader.State == ODataReaderState.EntityReferenceLink) { this.assert.IsTrue(this.testConfiguration.IsRequest, "EntityReferenceLink state should only be returned in requests."); ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)reader.Item; this.assert.IsNotNull(entityReferenceLink, "Reader should never report null entity reference link."); expandedItems.Add(entityReferenceLink); } else { this.assert.Fail("Unexpected reader state '" + reader.State + "' for reading a navigation link."); } reader.Read(); } this.assert.AreEqual(ODataReaderState.NavigationLinkEnd, reader.State, "Reader states don't match."); ODataNavigationLink navigationLink = (ODataNavigationLink)reader.Item; ODataNavigationLinkExpandedItemObjectModelAnnotation expandedLinkAnnotation = null; if (this.testConfiguration.IsRequest) { this.assert.IsTrue(expandedItems.Count > 0, "Deferred link (navigation link without any content) should only be returned in responses."); expandedLinkAnnotation = expandedItems.Count > 1 ? new ODataNavigationLinkExpandedItemObjectModelAnnotation() { ExpandedItem = expandedItems } : new ODataNavigationLinkExpandedItemObjectModelAnnotation() { ExpandedItem = expandedItems[0] }; } else { this.assert.IsTrue(expandedItems.Count <= 1, "In response each navigation link may contain at most one item in its content (entry or feed)."); if (expandedItems.Count == 1) { expandedLinkAnnotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation() { ExpandedItem = expandedItems[0] }; } } if (expandedLinkAnnotation != null) { navigationLink.SetAnnotation(expandedLinkAnnotation); } return navigationLink; }
/// <summary> /// Read an entry with an <see cref="ODataReader"/> positioned on the entry start. /// </summary> /// <param name="reader">The <see cref="ODataReader"/> to use for reading the entry.</param> /// <returns>An <see cref="ODataEntry"/>, possibly with annotations.</returns> private ODataEntry ReadEntry(ODataReader reader) { this.assert.AreEqual(ODataReaderState.EntryStart, reader.State, "Reader states don't match."); ODataEntry entry = (ODataEntry)reader.Item; ODataEntryPayloadOrderObjectModelAnnotation payloadOrderItems = this.storePayloadOrder ? new ODataEntryPayloadOrderObjectModelAnnotation() : null; ODataEntryNavigationLinksObjectModelAnnotation navigationLinks = new ODataEntryNavigationLinksObjectModelAnnotation(); AddEntryPayloadOrderItems(entry, payloadOrderItems); if (payloadOrderItems != null) { payloadOrderItems.AddStartEntry(); } while (reader.Read()) { if (reader.State == ODataReaderState.NavigationLinkStart) { int positionInProperties = entry.Properties.Count(); AddEntryPayloadOrderItems(entry, payloadOrderItems); ODataNavigationLink navigationLinkAtStart = (ODataNavigationLink)reader.Item; if (payloadOrderItems != null) { payloadOrderItems.AddODataNavigationLink(navigationLinkAtStart); } ODataNavigationLink navigationLink = this.ReadNavigationLink(reader); this.assert.AreSame(navigationLinkAtStart, navigationLink, "Expected the same navigation link instance."); navigationLinks.Add(navigationLink, positionInProperties + navigationLinks.Count); } else if (reader.State == ODataReaderState.EntryEnd) { // we are done reading this entry break; } else { this.assert.Fail("Unexpected reader state '" + reader.State + "' for reading an entry."); } } this.assert.AreEqual(ODataReaderState.EntryEnd, reader.State, "Reader states don't match."); ODataEntry entryAtEnd = (ODataEntry)reader.Item; this.assert.AreSame(entry, entryAtEnd, "Expected the same entry instance."); AddEntryPayloadOrderItems(entry, payloadOrderItems); entry.SetAnnotation(navigationLinks); if (this.storePayloadOrder) { entry.SetAnnotation(payloadOrderItems); } return entry; }
/// <summary> /// Read a feed with an <see cref="ODataReader"/> positioned on the feed start. /// </summary> /// <param name="reader">The <see cref="ODataReader"/> to use for reading the feed.</param> /// <returns>An <see cref="ODataFeed"/>, possibly with annotations.</returns> private ODataFeed ReadFeed(ODataReader reader) { this.assert.AreEqual(ODataReaderState.FeedStart, reader.State, "Reader states don't match."); ODataFeed feed = (ODataFeed)reader.Item; ODataFeedPayloadOrderObjectModelAnnotation payloadOrderItems = this.storePayloadOrder ? new ODataFeedPayloadOrderObjectModelAnnotation() : null; ODataFeedEntriesObjectModelAnnotation feedEntries = new ODataFeedEntriesObjectModelAnnotation(); AddFeedPayloadOrderItems(feed, payloadOrderItems); if (payloadOrderItems != null) { payloadOrderItems.AddStartFeed(); } while (reader.Read()) { if (reader.State == ODataReaderState.EntryStart) { AddFeedPayloadOrderItems(feed, payloadOrderItems); ODataEntry entry = this.ReadEntry(reader); if (payloadOrderItems != null) { payloadOrderItems.AddEntry(entry); } feedEntries.Add(entry); } else if (reader.State == ODataReaderState.FeedEnd) { // we are done reading the feed break; } else { this.assert.Fail("Unexpected reader state '" + reader.State + "' for reading a feed."); } } this.assert.AreEqual(ODataReaderState.FeedEnd, reader.State, "Reader states don't match."); ODataFeed feedAtEnd = (ODataFeed)reader.Item; this.assert.AreSame(feed, feedAtEnd, "Expected the same feed instance."); AddFeedPayloadOrderItems(feed, payloadOrderItems); feed.SetAnnotation(feedEntries); if (this.storePayloadOrder) { feed.SetAnnotation(payloadOrderItems); } return feed; }
private ODataResponse ReadResponse(ODataReader odataReader, bool includeResourceTypeInEntryProperties) { ResponseNode rootNode = null; var nodeStack = new Stack<ResponseNode>(); while (odataReader.Read()) { if (odataReader.State == ODataReaderState.Completed) break; switch (odataReader.State) { case ODataReaderState.FeedStart: StartFeed(nodeStack, CreateFeedAnnotaions(odataReader.Item as ODataFeed)); break; case ODataReaderState.FeedEnd: EndFeed(nodeStack, CreateFeedAnnotaions(odataReader.Item as ODataFeed), ref rootNode); break; case ODataReaderState.EntryStart: StartEntry(nodeStack); break; case ODataReaderState.EntryEnd: EndEntry(nodeStack, ref rootNode, odataReader.Item, includeResourceTypeInEntryProperties); break; case ODataReaderState.NavigationLinkStart: StartNavigationLink(nodeStack, (odataReader.Item as ODataNavigationLink).Name); break; case ODataReaderState.NavigationLinkEnd: EndNavigationLink(nodeStack); break; } } return rootNode.Feed != null ? ODataResponse.FromFeed(rootNode.Feed, rootNode.FeedAnnotations) : ODataResponse.FromEntry(rootNode.Entry); }