Пример #1
0
 protected override bool ReadAtFeedStartImplementation()
 {
     if ((this.atomEntryAndFeedDeserializer.XmlReader.NodeType == XmlNodeType.EndElement) || this.CurrentFeedState.FeedElementEmpty)
     {
         IODataAtomReaderFeedState currentFeedState = this.CurrentFeedState;
         ODataFeed currentFeed = base.CurrentFeed;
         if (this.atomInputContext.MessageReaderSettings.EnableAtomMetadataReading)
         {
             currentFeed.SetAnnotation <AtomFeedMetadata>(currentFeedState.AtomFeedMetadata);
         }
         this.ReplaceScope(ODataReaderState.FeedEnd);
     }
     else
     {
         this.ReadEntryStart();
     }
     return(true);
 }
        /// <summary>
        /// Reads the content of a feed (child nodes of the atom:feed).
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <param name="isExpandedLinkContent">true if the feed is inside an expanded link.</param>
        /// <returns>true if an entry was found or false if no more entries were found in the feed.</returns>
        /// <remarks>
        /// Pre-Condition:  Anything but Attribute           - the child node of the atom:feed element, can be pretty much anything, the method will skip over insignificant nodes and text nodes if found.
        /// Post-Condition: XmlNodeType.EndElement atom:feed - The end of the atom:feed element if no entry was found and the end of the feed was reached.
        ///                 XmlNodeType.Element atom:entry   - The start tag of the atom:entry element representing an entry in the feed.
        /// </remarks>
        internal bool ReadFeedContent(IODataAtomReaderFeedState feedState, bool isExpandedLinkContent)
        {
            Debug.Assert(feedState != null, "feedState != null");
            this.XmlReader.AssertNotBuffering();
            Debug.Assert(this.XmlReader.NodeType != XmlNodeType.Attribute, "The reader must be positioned on a child node of the atom:feed element.");

            bool entryFound = false;
            while (this.XmlReader.NodeType != XmlNodeType.EndElement)
            {
                if (this.XmlReader.NodeType != XmlNodeType.Element)
                {
                    Debug.Assert(this.XmlReader.NodeType != XmlNodeType.EndElement, "EndElement should have been handled already.");

                    // Skip everything but elements, including insignificant nodes, text nodes and CDATA nodes
                    this.XmlReader.Skip();
                    continue;
                }

                if (this.XmlReader.NamespaceEquals(this.AtomNamespace))
                {
                    if (this.ReadAtomElementInFeed(feedState, isExpandedLinkContent))
                    {
                        // We've found an entry - return.
                        entryFound = true;
                        break;
                    }
                }
                else if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace))
                {
                    AtomInstanceAnnotation annotation;

                    // We should not read the m:count element in request payloads.
                    if (this.ReadingResponse && !isExpandedLinkContent && this.XmlReader.LocalNameEquals(this.ODataCountElementName))
                    {
                        // m:count
                        // The default behavior is to disallow duplicates of feed/m:count element defined in ODATA spec.
                        this.ValidateDuplicateElement(feedState.HasCount);

                        // Note that we allow negative values to be read.
                        long countValue = (long)AtomValueUtils.ReadPrimitiveValue(this.XmlReader, EdmCoreModel.Instance.GetInt64(true));
                        feedState.Feed.Count = countValue;

                        // Read over the end element or the empty start element.
                        this.XmlReader.Read();

                        feedState.HasCount = true;
                    }
                    else if (this.atomAnnotationReader.TryReadAnnotation(out annotation))
                    {
                        // Note: There is some uncertainty over whether annotations on an expanded feed should appear on the ODataNavigationLink, the ODataFeed, or both.
                        // In the short term, we are failing when we encounter this scenario so that we can enable it later without causing a breaking change.
                        if (isExpandedLinkContent)
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_EncounteredAnnotationInNestedFeed);
                        }

                        // An annotation occurring as a direct child of a feed element can only target the feed it was found in.
                        // If we find an annotation breaking this rule, fail.
                        if (annotation.IsTargetingCurrentElement)
                        {
                            feedState.Feed.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.TermName, annotation.Value));
                        } 
                        else
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_AnnotationWithNonDotTarget(annotation.Target, annotation.TermName));
                        }
                    }
                    else
                    {
                        // Any other element in the m namespace is to be ignored.
                        this.XmlReader.Skip();
                    }
                }
                else
                {
                    // non-ATOM elements, ignore them
                    this.XmlReader.Skip();
                }
            }

            Debug.Assert(
                this.XmlReader.NodeType != XmlNodeType.EndElement ||
                    (this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomFeedElementName),
                "EndElement found but for element other than atom:feed.");
            Debug.Assert(
                this.XmlReader.NodeType != XmlNodeType.Element ||
                    (this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomEntryElementName),
                "Only atom:entry elements can be reported as entries.");

            this.AssertXmlCondition(XmlNodeType.Element, XmlNodeType.EndElement);
            this.XmlReader.AssertNotBuffering();
            return entryFound;
        }
        /// <summary>
        /// Reads the atom:link element with one of the standard relation values in the atom:feed element.
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <param name="linkRelation">The rel attribute value for the link.</param>
        /// <param name="linkHRef">The href attribute value for the link (or null if the href attribute was not present).</param>
        /// <param name="isExpandedLinkContent">true if the feed is inside an expanded link.</param>
        /// <returns>If the rel was one of the recognized standard relations and this method read the link
        /// the return value is true. Otherwise the method doesn't move the reader and returns false.</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element atom:link  - The atom:link element to read.
        /// Post-Condition:  Any                            - The node after the atom:link element if the link was read by this method.
        ///                  XmlNodeType.Element atom:link  - The atom:link element to read if the link was not read by this method.
        /// </remarks>
        private bool ReadAtomStandardRelationLinkInFeed(IODataAtomReaderFeedState feedState, string linkRelation, string linkHRef, bool isExpandedLinkContent)
        {
            Debug.Assert(feedState != null, "feedState != null");
            Debug.Assert(linkRelation != null, "linkRelation != null");
            this.XmlReader.AssertNotBuffering();
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomLinkElementName,
                "The XML reader must be on the atom:link element for this method to work.");

            if (string.CompareOrdinal(linkRelation, AtomConstants.AtomNextRelationAttributeValue) == 0)
            {
                // We should not read the next link in feed in request payloads.
                // WCF DS V2 Server ignores next link on a feed, since it's always request we also ignore it here.
                // Reader versioning: next link should be recognized only in >=V2 payloads.
                if (!this.ReadingResponse)
                {
                    // Return false which means the rel for the link was not recognized and it will be read as any other link.
                    return false;
                }

                // The default behavior is to disallow duplicates of feed/link[@rel='next'] element defined in ODATA spec.
                // We only target valid duplicates. We will not throw if there are duplicates with nonexistant href (client treats empty href as a valid relative URI).
                // WCF DS client behavior does not allow duplicate feed/link[@rel='next'] elements. WCF DS server never reads next link on responses.
                if (feedState.HasNextPageLink)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed(AtomConstants.AtomNextRelationAttributeValue));
                }

                // next link
                // [Client-ODataLib-Integration] Astoria client handling of next link of feed.
                // We decided to keep the behavior consistent with other links, which means ignore empty and nonexistant href. We decided to relax the client behavior
                // since V2 and allow missing href (we will ignore the link then) and also allow empty hread and treat that as a valid relative URL (client already did that).
                if (linkHRef != null)
                {
                    feedState.Feed.NextPageLink = this.ProcessUriFromPayload(linkHRef, this.XmlReader.XmlBaseUri);
                }

                feedState.HasNextPageLink = true;

                this.ReadLinkMetadataIfRequired(linkRelation, linkHRef, (linkMetadata) => { feedState.AtomFeedMetadata.NextPageLink = linkMetadata; });

                return true;
            }
            
            if (string.CompareOrdinal(linkRelation, AtomConstants.AtomSelfRelationAttributeValue) == 0)
            {
                // The default behavior is to disallow duplicates of feed/link[@rel='self'] element defined in ODATA spec.
                // We only target valid duplicates. We will not throw if there are duplicates with nonexistant href (client treats empty href as a valid relative URI).
                if (feedState.HasReadLink && this.AtomInputContext.UseDefaultFormatBehavior)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed(AtomConstants.AtomSelfRelationAttributeValue));
                }

                this.ReadLinkMetadataIfRequired(linkRelation, linkHRef, (linkMetadata) => { feedState.AtomFeedMetadata.SelfLink = linkMetadata; });

                feedState.HasReadLink = true;

                return true;
            }

            if (string.CompareOrdinal(linkRelation, AtomConstants.AtomDeltaRelationAttributeValue) == 0)
            {
                if (!this.ReadingResponse)
                {
                    // Return false which means the rel for the link was not recognized and it will be read as any other link.
                    return false;
                }

                if (feedState.HasDeltaLink)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed(AtomConstants.AtomDeltaRelationAttributeValue));
                }

                if (isExpandedLinkContent)
                {
                    throw new ODataException(ODataErrorStrings.ODataAtomEntryAndFeedDeserializer_EncounteredDeltaLinkInNestedFeed);
                }

                if (linkHRef != null)
                {
                    feedState.Feed.DeltaLink = this.ProcessUriFromPayload(linkHRef, this.XmlReader.XmlBaseUri);
                }

                this.ReadLinkMetadataIfRequired(linkRelation, linkHRef, (linkMetadata) => feedState.AtomFeedMetadata.AddLink(linkMetadata));

                feedState.HasDeltaLink = true;
                return true;
            }

            return false;
        }
        /// <summary>
        /// Reads an ATOM element inside the atom:feed from the input.
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <param name="isExpandedLinkContent">true if the feed is inside an expanded link.</param>
        /// <returns>true if the atom:entry element was found and the reader was not moved;
        /// false otherwise and the reader is positioned on the next node after the ATOM element.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element in ATOM namespace - The element in ATOM namespace to read.
        /// Post-Condition: Any                                   - The node after the ATOM element which was consumed.
        ///                 XmlNodeType.Element atom:entry        - The start of the atom:entry element (the reader did not move in this case).
        /// </remarks>
        private bool ReadAtomElementInFeed(IODataAtomReaderFeedState feedState, bool isExpandedLinkContent)
        {
            Debug.Assert(feedState != null, "feedState != null");
            this.XmlReader.AssertNotBuffering();
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace,
                "The reader must be on an element in the ATOM namespace for this method to work.");

            // ATOM elements
            if (this.XmlReader.LocalNameEquals(this.AtomEntryElementName))
            {
                // atom:entry
                return true;
            }

            if (this.XmlReader.LocalNameEquals(this.AtomLinkElementName))
            {
                // atom:link
                // NOTE: this method does not move the reader; thus a potential xml:base definition on the element
                //       works correctly for the values read from the attributes until we move the reader.
                string linkRelation, linkHRef;
                this.ReadAtomLinkRelationAndHRef(out linkRelation, out linkHRef);

                if (linkRelation != null)
                {
                    if (this.ReadAtomStandardRelationLinkInFeed(feedState, linkRelation, linkHRef, isExpandedLinkContent))
                    {
                        return false;
                    }

                    string unescapedLinkRelation = AtomUtils.UnescapeAtomLinkRelationAttribute(linkRelation);
                    if (unescapedLinkRelation != null)
                    {
                        string ianaRelation = AtomUtils.GetNameFromAtomLinkRelationAttribute(linkRelation, AtomConstants.IanaLinkRelationsNamespace);
                        if (ianaRelation != null && this.ReadAtomStandardRelationLinkInFeed(feedState, ianaRelation, linkHRef, isExpandedLinkContent))
                        {
                            return false;
                        }
                    }
                }

                if (this.ReadAtomMetadata)
                {
                    AtomLinkMetadata linkMetadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);
                    feedState.AtomFeedMetadata.AddLink(linkMetadata);
                }
                else
                {
                    // Ignore content of atom:link elements (unless they are expanded nav. links)
                    this.XmlReader.Skip();
                }
            }
            else if (this.XmlReader.LocalNameEquals(this.AtomIdElementName))
            {
                // atom:id
                // The id should be an IRI (so text only), but we already allow much more for entry/id, so we should do the same for feed/id
                // just to be consistent.
                // WCF DS V2 server fails on mixed and element content in the id element. The ReadElementValue also fails on mixed and element content
                // so this is a compatible behavior.
                string idValue = this.XmlReader.ReadElementValue();

                // We do not validate ID values on feeds when reading.
                feedState.Feed.Id = UriUtils.CreateUriAsEntryOrFeedId(idValue, UriKind.Absolute);
            }
            else
            {
                if (this.ReadAtomMetadata)
                {
                    this.FeedMetadataDeserializer.ReadAtomElementAsFeedMetadata(feedState.AtomFeedMetadata);
                }
                else
                {
                    this.XmlReader.Skip();
                }
            }

            return false;
        }
        /// <summary>
        /// Reads the content of a feed (child nodes of the atom:feed).
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <param name="isExpandedLinkContent">true if the feed is inside an expanded link.</param>
        /// <returns>true if an entry was found or false if no more entries were found in the feed.</returns>
        /// <remarks>
        /// Pre-Condition:  Anything but Attribute           - the child node of the atom:feed element, can be pretty much anything, the method will skip over insignificant nodes and text nodes if found.
        /// Post-Condition: XmlNodeType.EndElement atom:feed - The end of the atom:feed element if no entry was found and the end of the feed was reached.
        ///                 XmlNodeType.Element atom:entry   - The start tag of the atom:entry element representing an entry in the feed.
        /// </remarks>
        internal bool ReadFeedContent(IODataAtomReaderFeedState feedState, bool isExpandedLinkContent)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feedState != null, "feedState != null");
            this.XmlReader.AssertNotBuffering();
            Debug.Assert(this.XmlReader.NodeType != XmlNodeType.Attribute, "The reader must be positioned on a child node of the atom:feed element.");

            bool entryFound = false;
            while (this.XmlReader.NodeType != XmlNodeType.EndElement)
            {
                if (this.XmlReader.NodeType != XmlNodeType.Element)
                {
                    Debug.Assert(this.XmlReader.NodeType != XmlNodeType.EndElement, "EndElement should have been handled already.");

                    // Skip everything but elements, including insignificant nodes, text nodes and CDATA nodes
                    this.XmlReader.Skip();
                    continue;
                }

                if (this.XmlReader.NamespaceEquals(this.AtomNamespace))
                {
                    if (this.ReadAtomElementInFeed(feedState))
                    {
                        // We've found an entry - return.
                        entryFound = true;
                        break;
                    }
                }
                else if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataMetadataNamespace))
                {
                    if (this.ReadingResponse && this.Version >= ODataVersion.V2 && !isExpandedLinkContent && this.XmlReader.LocalNameEquals(this.ODataCountElementName))
                    {
                        // m:count
                        this.ValidateDuplicateElement(feedState.HasCount);

                        // Note that we allow negative values to be read.
                        long countValue = (long)AtomValueUtils.ReadPrimitiveValue(this.XmlReader, EdmCoreModel.Instance.GetInt64(true));
                        feedState.Feed.Count = countValue;

                        // Read over the end element or the empty start element.
                        this.XmlReader.Read();

                        feedState.HasCount = true;
                    }
                    else
                    {
                        // Any other element in the m namespace is to be ignored.
                        this.XmlReader.Skip();
                    }
                }
                else
                {
                    // non-ATOM elements, ignore them
                    this.XmlReader.Skip();
                }
            }

            Debug.Assert(
                this.XmlReader.NodeType != XmlNodeType.EndElement ||
                    (this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomFeedElementName),
                "EndElement found but for element other than atom:feed.");
            Debug.Assert(
                this.XmlReader.NodeType != XmlNodeType.Element ||
                    (this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomEntryElementName),
                "Only atom:entry elements can be reported as entries.");

            this.AssertXmlCondition(XmlNodeType.Element, XmlNodeType.EndElement);
            this.XmlReader.AssertNotBuffering();
            return entryFound;
        }
        /// <summary>
        /// Reads the atom:link element with one of the standard relation values in the atom:feed element.
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <param name="linkRelation">The rel attribute value for the link.</param>
        /// <param name="linkHRef">The href attribute value for the link (or null if the href attribute was not present).</param>
        /// <returns>If the rel was one of the recognized standard relations and this method read the link
        /// the return value is true. Otherwise the method doesn't move the reader and returns false.</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element atom:link  - The atom:link element to read.
        /// Post-Condition:  Any                            - The node after the atom:link element if the link was read by this method.
        ///                  XmlNodeType.Element atom:link  - The atom:link element to read if the link was not read by this method.
        /// </remarks>
        private bool ReadAtomStandardRelationLinkInFeed(IODataAtomReaderFeedState feedState, string linkRelation, string linkHRef)
        {
            Debug.Assert(feedState != null, "feedState != null");
            Debug.Assert(linkRelation != null, "linkRelation != null");
            this.XmlReader.AssertNotBuffering();
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomLinkElementName,
                "The XML reader must be on the atom:link element for this method to work.");

            if (string.CompareOrdinal(linkRelation, AtomConstants.AtomNextRelationAttributeValue) == 0)
            {
                if (!this.ReadingResponse || this.Version < ODataVersion.V2)
                {
                    // Return false which means the rel for the link was not recognized and it will be read as any other link.
                    return false;
                }

                if (feedState.HasNextPageLink)
                {
                    throw new ODataException(o.Strings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed(AtomConstants.AtomNextRelationAttributeValue));
                }

                // next link
                if (linkHRef != null)
                {
                    feedState.Feed.NextPageLink = this.ProcessUriFromPayload(linkHRef, this.XmlReader.XmlBaseUri);
                }

                feedState.HasNextPageLink = true;

                if (this.ReadAtomMetadata)
                {
                    AtomLinkMetadata linkMetadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);

                    feedState.AtomFeedMetadata.NextPageLink = linkMetadata;
                }
                else
                {
                    this.XmlReader.Skip();
                }

                return true;
            }
            
            if (string.CompareOrdinal(linkRelation, AtomConstants.AtomSelfRelationAttributeValue) == 0)
            {
                if (feedState.HasReadLink && this.AtomInputContext.UseDefaultFormatBehavior)
                {
                    throw new ODataException(o.Strings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed(AtomConstants.AtomSelfRelationAttributeValue));
                }

                if (this.ReadAtomMetadata)
                {
                    // Capture the ATOM metadata of the self link.
                    AtomLinkMetadata linkMetadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);
                    feedState.AtomFeedMetadata.SelfLink = linkMetadata;
                }
                else
                {
                    this.XmlReader.Skip();
                }

                feedState.HasReadLink = true;

                return true;
            }

            return false;
        }
        /// <summary>
        /// Reads an ATOM element inside the atom:feed from the input.
        /// </summary>
        /// <param name="feedState">The reader feed state for the feed being read.</param>
        /// <returns>true if the atom:entry element was found and the reader was not moved;
        /// false otherwise and the reader is positioned on the next node after the ATOM element.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element in ATOM namespace - The element in ATOM namespace to read.
        /// Post-Condition: Any                                   - The node after the ATOM element which was consumed.
        ///                 XmlNodeType.Element atom:entry        - The start of the atom:entry element (the reader did not move in this case).
        /// </remarks>
        private bool ReadAtomElementInFeed(IODataAtomReaderFeedState feedState)
        {
            Debug.Assert(feedState != null, "feedState != null");
            this.XmlReader.AssertNotBuffering();
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace,
                "The reader must be on an element in the ATOM namespace for this method to work.");

            // ATOM elements
            if (this.XmlReader.LocalNameEquals(this.AtomEntryElementName))
            {
                // atom:entry
                return true;
            }

            if (this.XmlReader.LocalNameEquals(this.AtomLinkElementName))
            {
                // atom:link
                // NOTE: this method does not move the reader; thus a potential xml:base definition on the element
                //       works correctly for the values read from the attributes until we move the reader.
                string linkRelation, linkHRef;
                this.ReadAtomLinkRelationAndHRef(out linkRelation, out linkHRef);

                if (linkRelation != null)
                {
                    if (this.ReadAtomStandardRelationLinkInFeed(feedState, linkRelation, linkHRef))
                    {
                        return false;
                    }

                    string unescapedLinkRelation = AtomUtils.UnescapeAtomLinkRelationAttribute(linkRelation);
                    if (unescapedLinkRelation != null)
                    {
                        string ianaRelation = AtomUtils.GetNameFromAtomLinkRelationAttribute(linkRelation, AtomConstants.IanaLinkRelationsNamespace);
                        if (ianaRelation != null && this.ReadAtomStandardRelationLinkInFeed(feedState, ianaRelation, linkHRef))
                        {
                            return false;
                        }
                    }
                }

                if (this.ReadAtomMetadata)
                {
                    AtomLinkMetadata linkMetadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);
                    AtomMetadataReaderUtils.AddLinkToFeedMetadata(feedState.AtomFeedMetadata, linkMetadata);
                }
                else
                {
                    this.XmlReader.Skip();
                }
            }
            else if (this.XmlReader.LocalNameEquals(this.AtomIdElementName))
            {
                // atom:id
                // The id should be an IRI (so text only), but we already allow much more for entry/id, so we should do the same for feed/id
                // just to be consistent.
                string idValue = this.XmlReader.ReadElementValue();

                feedState.Feed.Id = idValue;
            }
            else
            {
                if (this.ReadAtomMetadata)
                {
                    this.FeedMetadataDeserializer.ReadAtomElementAsFeedMetadata(feedState.AtomFeedMetadata);
                }
                else
                {
                    this.XmlReader.Skip();
                }
            }

            return false;
        }
 internal bool ReadFeedContent(IODataAtomReaderFeedState feedState, bool isExpandedLinkContent)
 {
     while (base.XmlReader.NodeType != XmlNodeType.EndElement)
     {
         if (base.XmlReader.NodeType != XmlNodeType.Element)
         {
             base.XmlReader.Skip();
         }
         else
         {
             if (base.XmlReader.NamespaceEquals(this.AtomNamespace))
             {
                 if (this.ReadAtomElementInFeed(feedState))
                 {
                     return true;
                 }
                 continue;
             }
             if (base.XmlReader.NamespaceEquals(base.XmlReader.ODataMetadataNamespace))
             {
                 if ((base.ReadingResponse && (base.Version >= ODataVersion.V2)) && (!isExpandedLinkContent && base.XmlReader.LocalNameEquals(this.ODataCountElementName)))
                 {
                     this.ValidateDuplicateElement(feedState.HasCount);
                     long num = (long) AtomValueUtils.ReadPrimitiveValue(base.XmlReader, EdmCoreModel.Instance.GetInt64(true));
                     feedState.Feed.Count = new long?(num);
                     base.XmlReader.Read();
                     feedState.HasCount = true;
                 }
                 else
                 {
                     base.XmlReader.Skip();
                 }
                 continue;
             }
             base.XmlReader.Skip();
         }
     }
     return false;
 }
 private bool ReadAtomStandardRelationLinkInFeed(IODataAtomReaderFeedState feedState, string linkRelation, string linkHRef)
 {
     if (string.CompareOrdinal(linkRelation, "next") == 0)
     {
         if (!base.ReadingResponse || (base.Version < ODataVersion.V2))
         {
             return false;
         }
         if (feedState.HasNextPageLink)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed("next"));
         }
         if (linkHRef != null)
         {
             feedState.Feed.NextPageLink = base.ProcessUriFromPayload(linkHRef, base.XmlReader.XmlBaseUri);
         }
         feedState.HasNextPageLink = true;
         if (this.ReadAtomMetadata)
         {
             AtomLinkMetadata metadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);
             feedState.AtomFeedMetadata.NextPageLink = metadata;
         }
         else
         {
             base.XmlReader.Skip();
         }
         return true;
     }
     if (string.CompareOrdinal(linkRelation, "self") != 0)
     {
         return false;
     }
     if (feedState.HasReadLink && base.AtomInputContext.UseDefaultFormatBehavior)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomEntryAndFeedDeserializer_MultipleLinksInFeed("self"));
     }
     if (this.ReadAtomMetadata)
     {
         AtomLinkMetadata metadata2 = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(linkRelation, linkHRef);
         feedState.AtomFeedMetadata.SelfLink = metadata2;
     }
     else
     {
         base.XmlReader.Skip();
     }
     feedState.HasReadLink = true;
     return true;
 }
 private bool ReadAtomElementInFeed(IODataAtomReaderFeedState feedState)
 {
     if (base.XmlReader.LocalNameEquals(this.AtomEntryElementName))
     {
         return true;
     }
     if (base.XmlReader.LocalNameEquals(this.AtomLinkElementName))
     {
         string str;
         string str2;
         this.ReadAtomLinkRelationAndHRef(out str, out str2);
         if (str != null)
         {
             if (this.ReadAtomStandardRelationLinkInFeed(feedState, str, str2))
             {
                 return false;
             }
             if (AtomUtils.UnescapeAtomLinkRelationAttribute(str) != null)
             {
                 string nameFromAtomLinkRelationAttribute = AtomUtils.GetNameFromAtomLinkRelationAttribute(str, "http://www.iana.org/assignments/relation/");
                 if ((nameFromAtomLinkRelationAttribute != null) && this.ReadAtomStandardRelationLinkInFeed(feedState, nameFromAtomLinkRelationAttribute, str2))
                 {
                     return false;
                 }
             }
         }
         if (this.ReadAtomMetadata)
         {
             AtomLinkMetadata linkMetadata = this.FeedMetadataDeserializer.ReadAtomLinkElementInFeed(str, str2);
             AtomMetadataReaderUtils.AddLinkToFeedMetadata(feedState.AtomFeedMetadata, linkMetadata);
         }
         else
         {
             base.XmlReader.Skip();
         }
     }
     else if (base.XmlReader.LocalNameEquals(this.AtomIdElementName))
     {
         string str5 = base.XmlReader.ReadElementValue();
         feedState.Feed.Id = str5;
     }
     else if (this.ReadAtomMetadata)
     {
         this.FeedMetadataDeserializer.ReadAtomElementAsFeedMetadata(feedState.AtomFeedMetadata);
     }
     else
     {
         base.XmlReader.Skip();
     }
     return false;
 }