private void WriteFeed(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            ODataSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(_edmCollectionType.ElementType());

            if (entrySerializer == null)
            {
                throw Error.NotSupported(SRResources.TypeCannotBeSerialized, _edmCollectionType.ElementType(), typeof(ODataMediaTypeFormatter).Name);
            }

            Contract.Assert(entrySerializer.ODataPayloadKind == ODataPayloadKind.Entry);

            IEnumerable enumerable = graph as IEnumerable; // Data to serialize

            if (enumerable != null)
            {
                ODataFeed feed = new ODataFeed();

                if (writeContext.EntitySet != null)
                {
                    IEntitySetLinkBuilder linkBuilder = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet);
                    Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(new FeedContext(writeContext.EntitySet, writeContext.UrlHelper, graph));
                    if (feedSelfLink != null)
                    {
                        feed.SetAnnotation(new AtomFeedMetadata()
                        {
                            SelfLink = new AtomLinkMetadata()
                            {
                                Relation = SelfLinkRelation, Href = feedSelfLink
                            }
                        });
                    }
                }

                // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ?
                feed.Id = FeedNamespace + _edmCollectionType.FullName();

                // If we have more OData format specific information apply it now.
                ODataResult odataFeedAnnotations = graph as ODataResult;
                if (odataFeedAnnotations != null)
                {
                    feed.Count        = odataFeedAnnotations.Count;
                    feed.NextPageLink = odataFeedAnnotations.NextPageLink;
                }

                writer.WriteStart(feed);

                foreach (object entry in enumerable)
                {
                    entrySerializer.WriteObjectInline(entry, writer, writeContext);
                }

                writer.WriteEnd();
            }
        }
        /// <summary>
        /// Create the <see cref="ODataFeed"/> to be written for the given feed instance.
        /// </summary>
        /// <param name="feedInstance">The instance representing the feed being written.</param>
        /// <param name="writeContext">The serializer context.</param>
        /// <returns>The created <see cref="ODataFeed"/> object.</returns>
        public virtual ODataFeed CreateODataFeed(IEnumerable feedInstance, ODataSerializerContext writeContext)
        {
            ODataFeed feed = new ODataFeed();

            if (writeContext.EntitySet != null)
            {
                IEdmModel model = writeContext.Model;
                EntitySetLinkBuilderAnnotation linkBuilder = model.GetEntitySetLinkBuilder(writeContext.EntitySet);
                FeedContext feedContext = new FeedContext
                {
                    Request      = writeContext.Request,
                    EntitySet    = writeContext.EntitySet,
                    Url          = writeContext.Url,
                    FeedInstance = feedInstance
                };

                Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext);
                if (feedSelfLink != null)
                {
                    feed.SetAnnotation(new AtomFeedMetadata()
                    {
                        SelfLink = new AtomLinkMetadata()
                        {
                            Relation = "self", Href = feedSelfLink
                        }
                    });
                }
            }

            // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ?
            feed.Id = "http://schemas.datacontract.org/2004/07/" + EntityCollectionType.FullName();

            // If we have more OData format specific information apply it now.
            PageResult odataFeedAnnotations = feedInstance as PageResult;

            if (odataFeedAnnotations != null)
            {
                feed.Count        = odataFeedAnnotations.Count;
                feed.NextPageLink = odataFeedAnnotations.NextPageLink;
            }
            else if (writeContext.Request != null)
            {
                feed.NextPageLink = writeContext.Request.GetNextPageLink();

                long?inlineCount = writeContext.Request.GetInlineCount();
                if (inlineCount.HasValue)
                {
                    feed.Count = inlineCount.Value;
                }
            }

            return(feed);
        }
Exemple #3
0
        private static void AddFeedMetadata(EntitySetInstance payloadElement, ODataFeed feed)
        {
            AtomFeedMetadata metadata = CreateFeedMetadata(payloadElement.Annotations.OfType <XmlTreeAnnotation>(), feed);

            // Fix up metadata for baselining
            metadata = metadata.Fixup();

            if (metadata != null)
            {
                feed.SetAnnotation <AtomFeedMetadata>(metadata);
            }
        }
Exemple #4
0
 public static MaterializerFeed CreateFeed(ODataFeed feed, IEnumerable <ODataEntry> entries)
 {
     if (entries == null)
     {
         entries = Enumerable.Empty <ODataEntry>();
     }
     else
     {
         feed.SetAnnotation <IEnumerable <ODataEntry> >(entries);
     }
     return(new MaterializerFeed(feed, entries));
 }
        public static AtomFeedMetadata Atom(this ODataFeed feed)
        {
            ExceptionUtils.CheckArgumentNotNull <ODataFeed>(feed, "feed");
            AtomFeedMetadata annotation = feed.GetAnnotation <AtomFeedMetadata>();

            if (annotation == null)
            {
                annotation = new AtomFeedMetadata();
                feed.SetAnnotation <AtomFeedMetadata>(annotation);
            }
            return(annotation);
        }
Exemple #6
0
        /// <summary>
        /// Creates the materializer feed.
        /// </summary>
        /// <param name="feed">The feed.</param>
        /// <param name="entries">The entries.</param>
        /// <returns>The materializer feed.</returns>
        public static MaterializerFeed CreateFeed(ODataFeed feed, IEnumerable <ODataEntry> entries)
        {
            Debug.Assert(feed.GetAnnotation <IEnumerable <ODataEntry> >() == null, "Feed state has already been created.");
            if (entries == null)
            {
                entries = Enumerable.Empty <ODataEntry>();
            }
            else
            {
                feed.SetAnnotation <IEnumerable <ODataEntry> >(entries);
            }

            return(new MaterializerFeed(feed, entries));
        }
        public static AtomFeedMetadata Atom(this ODataFeed feed)
        {
            ExceptionUtils.CheckArgumentNotNull(feed, "feed");

            AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>();

            if (feedMetadata == null)
            {
                feedMetadata = new AtomFeedMetadata();
                feed.SetAnnotation(feedMetadata);
            }

            return(feedMetadata);
        }
 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);
 }
Exemple #9
0
        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();
        }
Exemple #10
0
        /// <summary>
        /// Writes the feed element for the atom payload.
        /// </summary>
        /// <param name="expanded">Expanded properties for the result.</param>
        /// <param name="elements">Collection of entries in the feed element.</param>
        /// <param name="expectedType">ExpectedType of the elements in the collection.</param>
        /// <param name="title">Title of the feed element.</param>
        /// <param name="getRelativeUri">Callback to get the relative uri of the feed.</param>
        /// <param name="getAbsoluteUri">Callback to get the absolute uri of the feed.</param>
        /// <param name="topLevel">True if the feed is the top level feed, otherwise false for the inner expanded feed.</param>
        private void WriteFeedElements(
            IExpandedResult expanded,
            QueryResultInfo elements,
            ResourceType expectedType,
            string title,
            Func <Uri> getRelativeUri,
            Func <Uri> getAbsoluteUri,
            bool topLevel)
        {
            Debug.Assert(elements != null, "elements != null");
            Debug.Assert(expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType, "expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType");
            Debug.Assert(!string.IsNullOrEmpty(title), "!string.IsNullOrEmpty(title)");

            ODataFeed feed = new ODataFeed();

            feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName
            });

            // Write the other elements for the feed
            this.PayloadMetadataPropertyManager.SetId(feed, () => getAbsoluteUri());

#pragma warning disable 618
            if (this.contentFormat == ODataFormat.Atom)
#pragma warning restore 618
            {
                // Create the atom feed metadata and set the self link and title value.
                AtomFeedMetadata feedMetadata = new AtomFeedMetadata();
                feed.SetAnnotation(feedMetadata);
                feedMetadata.Title = new AtomTextConstruct {
                    Text = title
                };
                feedMetadata.SelfLink = new AtomLinkMetadata {
                    Href = getRelativeUri(), Title = title
                };
            }

            // support for $count
            // in ATOM we write it at the beginning (we always have)
            //   in JSON for backward compatiblity reasons we write it at the end, so we must not fill it here.
            if (topLevel && this.RequestDescription.CountOption == RequestQueryCountOption.CountQuery)
            {
                feed.Count = this.RequestDescription.CountValue;
            }

            var feedArgs = elements.GetDataServiceODataWriterFeedArgs(feed, this.Service.OperationContext);
            this.dataServicesODataWriter.WriteStart(feedArgs);
            object          lastObject            = null;
            IExpandedResult lastExpandedSkipToken = null;
            while (elements.HasMoved)
            {
                object          o         = elements.Current;
                IExpandedResult skipToken = this.GetSkipToken(expanded);

                if (o != null)
                {
                    IExpandedResult expandedO = o as IExpandedResult;
                    if (expandedO != null)
                    {
                        expanded  = expandedO;
                        o         = GetExpandedElement(expanded);
                        skipToken = this.GetSkipToken(expanded);
                    }

                    this.WriteEntry(expanded, o, true /*resourceInstanceInFeed*/, expectedType);
                }

                elements.MoveNext();
                lastObject            = o;
                lastExpandedSkipToken = skipToken;
            }

            // After looping through the objects in the sequence, decide if we need to write the next
            // page link and if yes, write it by invoking the delegate
            if (this.NeedNextPageLink(elements))
            {
                this.PayloadMetadataPropertyManager.SetNextPageLink(
                    feed,
                    this.AbsoluteServiceUri,
                    this.GetNextLinkUri(lastObject, lastExpandedSkipToken, getAbsoluteUri()));
            }

            this.dataServicesODataWriter.WriteEnd(feedArgs);
#if ASTORIA_FF_CALLBACKS
            this.Service.InternalOnWriteFeed(feed);
#endif
        }
Exemple #11
0
        internal static ODataItem ReadEntryOrFeed(ODataReader odataReader, ODataDeserializerContext readContext)
        {
            ODataItem         topLevelItem = null;
            Stack <ODataItem> itemsStack   = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                switch (odataReader.State)
                {
                case ODataReaderState.EntryStart:
                    ODataEntry           entry           = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation entryAnnotation = null;
                    if (entry != null)
                    {
                        entryAnnotation = new ODataEntryAnnotation();
                        entry.SetAnnotation(entryAnnotation);
                    }

                    if (itemsStack.Count == 0)
                    {
                        Contract.Assert(entry != null, "The top-level entry can never be null.");
                        topLevelItem = entry;
                    }
                    else
                    {
                        ODataItem parentItem = itemsStack.Peek();
                        ODataFeed parentFeed = parentItem as ODataFeed;
                        if (parentFeed != null)
                        {
                            ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>();
                            Contract.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it.");
                            parentFeedAnnotation.Add(entry);
                        }
                        else
                        {
                            ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)parentItem;
                            ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                            Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                            Contract.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child.");
                            Contract.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child.");
                            parentNavigationLinkAnnotation.Add(entry);
                        }
                    }
                    itemsStack.Push(entry);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.EntryEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.NavigationLinkStart:
                    ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item;
                    Contract.Assert(navigationLink != null, "Navigation link should never be null.");

                    navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation());
                    Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item.");
                    {
                        ODataEntry           parentEntry           = (ODataEntry)itemsStack.Peek();
                        ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>();
                        Contract.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the entry annotation on it.");
                        parentEntryAnnotation.Add(navigationLink);
                    }

                    itemsStack.Push(navigationLink);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.NavigationLinkEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.FeedStart:
                    ODataFeed feed = (ODataFeed)odataReader.Item;
                    Contract.Assert(feed != null, "Feed should never be null.");

                    feed.SetAnnotation(new ODataFeedAnnotation());
                    if (itemsStack.Count > 0)
                    {
                        ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek();
                        Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link.");
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        Contract.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child.");
                        parentNavigationLinkAnnotation.Add(feed);
                    }
                    else
                    {
                        topLevelItem = feed;
                    }

                    itemsStack.Push(feed);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.FeedEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.EntityReferenceLink:
                    ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item;
                    Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null.");

                    Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        parentNavigationLinkAnnotation.Add(entityReferenceLink);
                    }

                    break;

                default:
                    Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state.");
                    break;
                }
            }

            Contract.Assert(odataReader.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 void FeedAndEntryUpdatedTimeTests()
        {
            ODataFeed defaultFeedWithEmptyMetadata = ObjectModelUtils.CreateDefaultFeed();

            defaultFeedWithEmptyMetadata.SetAnnotation <AtomFeedMetadata>(new AtomFeedMetadata());
            ODataEntry defaultEntryWithEmptyMetadata = ObjectModelUtils.CreateDefaultEntry();

            defaultEntryWithEmptyMetadata.SetAnnotation <AtomEntryMetadata>(new AtomEntryMetadata());

            IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testPayloads =
                new[]
            {
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeed()),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultFeedWithEmptyMetadata),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeedWithAtomMetadata()),
            }.PayloadCases(WriterPayloads.FeedPayloads)
            .Concat((new[]
            {
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntry()),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultEntryWithEmptyMetadata),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntryWithAtomMetadata()),
            }.PayloadCases(WriterPayloads.EntryPayloads)));

            this.CombinatorialEngineProvider.RunCombinations(
                testPayloads,
                this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent.Where(tc => !tc.IsRequest),
                (testPayload, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                string lastUpdatedTimeStr = null;
                using (var memoryStream = new MemoryStream())
                {
                    using (var testMemoryStream = TestWriterUtils.CreateTestStream(testConfiguration, memoryStream, ignoreDispose: true))
                    {
                        bool feedWriter         = testPayload.PayloadItems[0] is ODataFeed;
                        TestMessage testMessage = null;
                        Exception exception     = TestExceptionUtils.RunCatching(() =>
                        {
                            using (var messageWriter = TestWriterUtils.CreateMessageWriter(testMemoryStream, testConfiguration, this.Assert, out testMessage, null, testPayload.Model))
                            {
                                ODataWriter writer = messageWriter.CreateODataWriter(feedWriter);
                                TestWriterUtils.WritePayload(messageWriter, writer, true, testPayload.PayloadItems, testPayload.ThrowUserExceptionAt);
                            }
                        });
                        this.Assert.IsNull(exception, "Received exception but expected none.");
                    }

                    memoryStream.Position = 0;
                    XElement result       = XElement.Load(memoryStream);
                    foreach (XElement updated in result.Descendants(((XNamespace)TestAtomConstants.AtomNamespace) + "updated"))
                    {
                        if (updated.Value != ObjectModelUtils.DefaultFeedUpdated && updated.Value != ObjectModelUtils.DefaultEntryUpdated)
                        {
                            if (lastUpdatedTimeStr == null)
                            {
                                lastUpdatedTimeStr = updated.Value;
                            }
                            else
                            {
                                this.Assert.AreEqual(lastUpdatedTimeStr, updated.Value, "<atom:updated> should contain the same value.");
                            }
                        }
                    }
                }
            });
        }
        private void WriteFeed(object graph, ODataWriter writer, ODataSerializerContext writeContext)
        {
            IEnumerable enumerable = graph as IEnumerable; // Data to serialize

            if (enumerable != null)
            {
                ODataFeed feed = new ODataFeed();

                if (writeContext.EntitySet != null)
                {
                    IEntitySetLinkBuilder linkBuilder = SerializerProvider.EdmModel.GetEntitySetLinkBuilder(writeContext.EntitySet);
                    FeedContext           feedContext = new FeedContext
                    {
                        EntitySet    = writeContext.EntitySet,
                        UrlHelper    = writeContext.UrlHelper,
                        PathHandler  = writeContext.PathHandler,
                        FeedInstance = graph
                    };

                    Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext);
                    if (feedSelfLink != null)
                    {
                        feed.SetAnnotation(new AtomFeedMetadata()
                        {
                            SelfLink = new AtomLinkMetadata()
                            {
                                Relation = SelfLinkRelation, Href = feedSelfLink
                            }
                        });
                    }
                }

                // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ?
                feed.Id = FeedNamespace + _edmCollectionType.FullName();

                // If we have more OData format specific information apply it now.
                ODataResult odataFeedAnnotations = graph as ODataResult;
                if (odataFeedAnnotations != null)
                {
                    feed.Count        = odataFeedAnnotations.Count;
                    feed.NextPageLink = odataFeedAnnotations.NextPageLink;
                }
                else
                {
                    object             nextPageLinkPropertyValue;
                    HttpRequestMessage request = writeContext.Request;
                    if (request != null && request.Properties.TryGetValue(ODataQueryOptions.NextPageLinkPropertyKey, out nextPageLinkPropertyValue))
                    {
                        Uri nextPageLink = nextPageLinkPropertyValue as Uri;
                        if (nextPageLink != null)
                        {
                            feed.NextPageLink = nextPageLink;
                        }
                    }
                }

                writer.WriteStart(feed);

                foreach (object entry in enumerable)
                {
                    if (entry == null)
                    {
                        throw Error.NotSupported(SRResources.NullElementInCollection);
                    }

                    ODataSerializer entrySerializer = SerializerProvider.GetODataPayloadSerializer(entry.GetType());
                    if (entrySerializer == null)
                    {
                        throw Error.NotSupported(SRResources.TypeCannotBeSerialized, entry.GetType(), typeof(ODataMediaTypeFormatter).Name);
                    }

                    Contract.Assert(entrySerializer.ODataPayloadKind == ODataPayloadKind.Entry);

                    entrySerializer.WriteObjectInline(entry, writer, writeContext);
                }

                writer.WriteEnd();
            }
        }
        /// <summary>
        /// Create the <see cref="ODataFeed"/> to be written for the given feed instance.
        /// </summary>
        /// <param name="feedInstance">The instance representing the feed being written.</param>
        /// <param name="feedType">The EDM type of the feed being written.</param>
        /// <param name="writeContext">The serializer context.</param>
        /// <returns>The created <see cref="ODataFeed"/> object.</returns>
        public virtual ODataFeed CreateODataFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType,
                                                 ODataSerializerContext writeContext)
        {
            ODataFeed feed = new ODataFeed();

            if (writeContext.EntitySet != null)
            {
                IEdmModel model = writeContext.Model;
                EntitySetLinkBuilderAnnotation linkBuilder = model.GetEntitySetLinkBuilder(writeContext.EntitySet);
                FeedContext feedContext = new FeedContext
                {
                    Request        = writeContext.Request,
                    RequestContext = writeContext.RequestContext,
                    EntitySet      = writeContext.EntitySet,
                    Url            = writeContext.Url,
                    FeedInstance   = feedInstance
                };

                Uri feedSelfLink = linkBuilder.BuildFeedSelfLink(feedContext);
                if (feedSelfLink != null)
                {
                    feed.SetAnnotation(new AtomFeedMetadata()
                    {
                        SelfLink = new AtomLinkMetadata()
                        {
                            Relation = "self", Href = feedSelfLink
                        }
                    });
                }
            }

            // TODO: Bug 467590: remove the hardcoded feed id. Get support for it from the model builder ?
            feed.Id = "http://schemas.datacontract.org/2004/07/" + feedType.FullName();

            if (writeContext.ExpandedEntity == null)
            {
                // If we have more OData format specific information apply it now, only if we are the root feed.
                PageResult odataFeedAnnotations = feedInstance as PageResult;
                if (odataFeedAnnotations != null)
                {
                    feed.Count        = odataFeedAnnotations.Count;
                    feed.NextPageLink = odataFeedAnnotations.NextPageLink;
                }
                else if (writeContext.Request != null)
                {
                    feed.NextPageLink = writeContext.Request.ODataProperties().NextLink;

                    long?inlineCount = writeContext.Request.ODataProperties().TotalCount;
                    if (inlineCount.HasValue)
                    {
                        feed.Count = inlineCount.Value;
                    }
                }
            }
            else
            {
                // nested feed
                ITruncatedCollection truncatedCollection = feedInstance as ITruncatedCollection;
                if (truncatedCollection != null && truncatedCollection.IsTruncated)
                {
                    feed.NextPageLink = GetNestedNextPageLink(writeContext, truncatedCollection.PageSize);
                }
            }

            return(feed);
        }
Exemple #15
0
        private void WriteFeedElements(IExpandedResult expanded, IEnumerator elements, ResourceType expectedType, string title, Uri relativeUri, Uri absoluteUri, bool hasMoved, bool topLevel)
        {
            ODataFeed feed = new ODataFeed {
                Id = absoluteUri.AbsoluteUri
            };
            AtomFeedMetadata annotation = new AtomFeedMetadata();

            feed.SetAnnotation <AtomFeedMetadata>(annotation);
            AtomTextConstruct construct = new AtomTextConstruct {
                Text = title
            };

            annotation.Title = construct;
            AtomLinkMetadata metadata2 = new AtomLinkMetadata {
                Href  = relativeUri,
                Title = title
            };

            annotation.SelfLink = metadata2;
            bool flag = false;

            if (topLevel && (base.RequestDescription.CountOption == RequestQueryCountOption.Inline))
            {
                flag = this.contentFormat == ODataFormat.VerboseJson;
                if (!flag)
                {
                    feed.Count = new long?(base.RequestDescription.CountValue);
                }
            }
            this.odataWriter.WriteStart(feed);
            try
            {
                object          lastObject = null;
                IExpandedResult skipTokenExpandedResult = null;
                while (hasMoved)
                {
                    object          current   = elements.Current;
                    IExpandedResult skipToken = base.GetSkipToken(expanded);
                    if (current != null)
                    {
                        IExpandedResult result3 = current as IExpandedResult;
                        if (result3 != null)
                        {
                            expanded  = result3;
                            current   = Serializer.GetExpandedElement(expanded);
                            skipToken = base.GetSkipToken(expanded);
                        }
                        this.WriteEntry(expanded, current, true, expectedType);
                    }
                    hasMoved   = elements.MoveNext();
                    lastObject = current;
                    skipTokenExpandedResult = skipToken;
                }
                if (flag)
                {
                    feed.Count = new long?(base.RequestDescription.CountValue);
                }
                if (base.NeedNextPageLink(elements))
                {
                    feed.NextPageLink = base.GetNextLinkUri(lastObject, skipTokenExpandedResult, absoluteUri);
                }
            }
            finally
            {
                if (!topLevel)
                {
                    WebUtil.Dispose(elements);
                }
            }
            this.odataWriter.WriteEnd();
        }
        /// <summary>
        /// Reads an entry from the <paramref name="odataReader"/> and all it's children including expanded entries and feeds.
        /// </summary>
        /// <param name="odataReader">The ODataReader to read from.</param>
        /// <param name="topLevelSegmentInfo">The segment info for the top-level entry to read.</param>
        /// <returns>The <see cref="ODataEntry"/> with annotations which store the navigation links and their expanded values.</returns>
        private ODataEntry ReadEntry(ODataReader odataReader, SegmentInfo topLevelSegmentInfo)
        {
            Debug.Assert(odataReader != null, "odataReader != null");
            Debug.Assert(odataReader.State == ODataReaderState.Start, "The ODataReader must not have been used yet.");
            Debug.Assert(topLevelSegmentInfo != null, "topLevelSegmentInfo != null");

            ODataEntry        topLevelEntry = null;
            Stack <ODataItem> itemsStack    = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                // Don't let the item stack grow larger than we can process later. Also lets us to fail and report the recursion depth limit error before ODL does.
                if (itemsStack.Count >= RecursionLimit)
                {
                    throw DataServiceException.CreateDeepRecursion(RecursionLimit);
                }

                switch (odataReader.State)
                {
                case ODataReaderState.EntryStart:
                    ODataEntry           entry           = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation entryAnnotation = null;
                    if (entry != null)
                    {
                        entryAnnotation = new ODataEntryAnnotation();
                        entry.SetAnnotation(entryAnnotation);
                    }

                    if (itemsStack.Count == 0)
                    {
                        Debug.Assert(entry != null, "The top-level entry can never be null.");
                        topLevelEntry = entry;

                        // For top-level entry, create the entry resource here.
                        // This is needed since the creation of the resource may fail (especially if this is an update in which case
                        // we evaluate the URL query, which may return no results and thus we would fail with 404)
                        // and we need to report that failure rather then potential other failures caused by the properties in the entry in question.
                        this.CreateEntityResource(topLevelSegmentInfo, entry, entryAnnotation, /*topLevel*/ true);
                    }
                    else
                    {
                        ODataItem parentItem = itemsStack.Peek();
                        ODataFeed parentFeed = parentItem as ODataFeed;
                        if (parentFeed != null)
                        {
                            ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>();
                            Debug.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it.");
                            parentFeedAnnotation.Add(entry);
                        }
                        else
                        {
                            ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)parentItem;
                            ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                            Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                            Debug.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child.");
                            Debug.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child.");
                            parentNavigationLinkAnnotation.Add(entry);
                        }
                    }

                    itemsStack.Push(entry);
                    break;

                case ODataReaderState.EntryEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    break;

                case ODataReaderState.NavigationLinkStart:
                    ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item;
                    Debug.Assert(navigationLink != null, "Navigation link should never be null.");

                    navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation());
                    Debug.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item.");
                    {
                        ODataEntry           parentEntry           = (ODataEntry)itemsStack.Peek();
                        ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>();
                        Debug.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the navigation link annotation on it.");
                        parentEntryAnnotation.Add(navigationLink);
                    }

                    itemsStack.Push(navigationLink);
                    break;

                case ODataReaderState.NavigationLinkEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.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)odataReader.Item;
                    Debug.Assert(feed != null, "Feed should never be null.");

                    feed.SetAnnotation(new ODataFeedAnnotation());
                    Debug.Assert(itemsStack.Count > 0, "Since we always start reading entry, we should never get a feed as the top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        Debug.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child.");
                        parentNavigationLinkAnnotation.Add(feed);
                    }

                    itemsStack.Push(feed);
                    break;

                case ODataReaderState.FeedEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    break;

                case ODataReaderState.EntityReferenceLink:
                    ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item;
                    Debug.Assert(entityReferenceLink != null, "Entity reference link should never be null.");

                    Debug.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        parentNavigationLinkAnnotation.Add(entityReferenceLink);
                    }

                    break;

                default:
                    Debug.Assert(false, "We should never get here, it means the ODataReader reported a wrong state.");
                    break;
                }
            }

            Debug.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now.");
            Debug.Assert(topLevelEntry != null, "A top level entry should have been read by now.");
            return(topLevelEntry);
        }
        private ODataEntry ReadEntry(ODataReader odataReader, System.Data.Services.SegmentInfo topLevelSegmentInfo)
        {
            ODataEntry        entry = null;
            Stack <ODataItem> stack = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                if (stack.Count >= 100)
                {
                    throw DataServiceException.CreateDeepRecursion(100);
                }
                switch (odataReader.State)
                {
                case ODataReaderState.FeedStart:
                {
                    ODataFeed feed2 = (ODataFeed)odataReader.Item;
                    feed2.SetAnnotation <ODataFeedAnnotation>(new ODataFeedAnnotation());
                    ODataNavigationLink link3 = (ODataNavigationLink)stack.Peek();
                    link3.GetAnnotation <ODataNavigationLinkAnnotation>().Add(feed2);
                    stack.Push(feed2);
                    break;
                }

                case ODataReaderState.FeedEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.EntryStart:
                {
                    ODataEntry           entry2     = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation annotation = null;
                    if (entry2 != null)
                    {
                        annotation = new ODataEntryAnnotation();
                        entry2.SetAnnotation <ODataEntryAnnotation>(annotation);
                    }
                    if (stack.Count == 0)
                    {
                        entry = entry2;
                        this.CreateEntityResource(topLevelSegmentInfo, entry2, annotation, true);
                    }
                    else
                    {
                        ODataItem item = stack.Peek();
                        ODataFeed feed = item as ODataFeed;
                        if (feed != null)
                        {
                            feed.GetAnnotation <ODataFeedAnnotation>().Add(entry2);
                        }
                        else
                        {
                            ODataNavigationLink link = (ODataNavigationLink)item;
                            link.GetAnnotation <ODataNavigationLinkAnnotation>().Add(entry2);
                        }
                    }
                    stack.Push(entry2);
                    break;
                }

                case ODataReaderState.EntryEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.NavigationLinkStart:
                {
                    ODataNavigationLink link2 = (ODataNavigationLink)odataReader.Item;
                    link2.SetAnnotation <ODataNavigationLinkAnnotation>(new ODataNavigationLinkAnnotation());
                    ODataEntry entry3 = (ODataEntry)stack.Peek();
                    entry3.GetAnnotation <ODataEntryAnnotation>().Add(link2);
                    stack.Push(link2);
                    break;
                }

                case ODataReaderState.NavigationLinkEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.EntityReferenceLink:
                {
                    ODataEntityReferenceLink link4 = (ODataEntityReferenceLink)odataReader.Item;
                    ODataNavigationLink      link5 = (ODataNavigationLink)stack.Peek();
                    link5.GetAnnotation <ODataNavigationLinkAnnotation>().Add(link4);
                    break;
                }
                }
            }
            return(entry);
        }