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;
            }