private void Read(Lazy<ODataReader> lazyReader) { foreach (var state in this.expectedStates) { lazyReader.Value.Read(); ExceptionUtilities.Assert(lazyReader.Value.State == state, "Expected %1, Found %2", state, lazyReader.Value.State); switch (state) { case ODataReaderState.FeedStart: if (readItems.Count > 0) { ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek(); var annotation = navLink.GetAnnotation<ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation(); navLink.SetAnnotation(annotation); } annotation.ExpandedItem = lazyReader.Value.Item; } readItems.Push(lazyReader.Value.Item); break; case ODataReaderState.EntryStart: var currentEntry = (ODataEntry)lazyReader.Value.Item; if (readItems.Count > 0) { ODataFeed feed = readItems.Peek() as ODataFeed; if (feed != null) { var annotation = feed.GetAnnotation<ODataFeedEntriesObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataFeedEntriesObjectModelAnnotation(); feed.SetAnnotation(annotation); } annotation.Add((ODataEntry)lazyReader.Value.Item); } else { ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek(); var annotation = navLink.GetAnnotation<ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (annotation == null) { annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation(); navLink.SetAnnotation(annotation); } annotation.ExpandedItem = currentEntry; } } readItems.Push(currentEntry); break; case ODataReaderState.NavigationLinkStart: ODataEntry entry = (ODataEntry)readItems.Peek(); var navLinksAnnotation = entry.GetAnnotation<ODataEntryNavigationLinksObjectModelAnnotation>(); if (navLinksAnnotation == null) { navLinksAnnotation = new ODataEntryNavigationLinksObjectModelAnnotation(); entry.SetAnnotation(navLinksAnnotation); } navLinksAnnotation.Add((ODataNavigationLink)lazyReader.Value.Item, entry.Properties.Count() + navLinksAnnotation.Count); readItems.Push(lazyReader.Value.Item); break; case ODataReaderState.EntryEnd: case ODataReaderState.FeedEnd: case ODataReaderState.NavigationLinkEnd: if (readItems.Count() > 1) readItems.Pop(); break; } } this.expectedStates.Clear(); }
/// <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; }