public void CreateODataFeed_Sets_FeedSelfLink()
        {
            // Arrange
            var feedInstance = new object[0];
            ODataSerializerContext writeContext = new ODataSerializerContext {
                EntitySet = _customerSet, Model = _model, Request = new HttpRequestMessage()
            };

            writeContext.Url = new UrlHelper(writeContext.Request);
            ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider());
            Uri feedSelfLink = new Uri("http://feed_self_link/");
            EntitySetLinkBuilderAnnotation linkBuilder = new MockEntitySetLinkBuilderAnnotation
            {
                FeedSelfLinkBuilder = (context) =>
                {
                    Assert.Equal(_customerSet, context.EntitySet);
                    Assert.Equal(feedInstance, context.FeedInstance);
                    Assert.Equal(writeContext.Request, context.Request);
                    Assert.Equal(writeContext.Url, context.Url);
                    return(feedSelfLink);
                }
            };

            _model.SetEntitySetLinkBuilder(_customerSet, linkBuilder);

            // Act
            ODataFeed feed = serializer.CreateODataFeed(feedInstance, _customersType, writeContext);

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

            Assert.Equal(feedSelfLink, feedMetadata.SelfLink.Href);
            Assert.Equal("self", feedMetadata.SelfLink.Relation);
        }
        /// <summary>
        /// Write the ATOM metadata for a feed
        /// </summary>
        /// <param name="writer">The Xml writer to write to.</param>
        /// <param name="baseUri">The base Uri of the document or null if none was specified.</param>
        /// <param name="feed">The feed for which to write the metadata.</param>
        internal static void WriteFeedMetadata(XmlWriter writer, Uri baseUri, ODataFeed feed)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(feed != null, "feed != null");

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

            if (feedMetadata == null)
            {
                // create the required metadata elements with default values.

                // <atom:id>idValue</atom:id>
                Debug.Assert(!string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now.");
                ODataAtomWriterUtils.WriteElementWithTextContent(
                    writer,
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomIdElementName,
                    AtomConstants.AtomNamespace,
                    feed.Id);

                // <atom:title></atom:title>
                ODataAtomWriterUtils.WriteEmptyElement(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace);

                // <atom:updated>dateTimeOffset</atom:updated>
                ODataAtomWriterUtils.WriteElementWithTextContent(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(DateTimeOffset.UtcNow));
            }
            else
            {
                WriteFeedMetadata(writer, baseUri, feedMetadata, feed);
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the <see cref="EntityType"/> of the specified entry or feed payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to get the entity type for.</param>
        /// <param name="model">The model to find the entity type in.</param>
        /// <returns>The <see cref="EntityType"/> of the <paramref name="payloadElement"/>.</returns>
        public static IEdmEntityType GetPayloadElementEntityType(ODataAnnotatable payloadElement, EdmModel model)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckArgumentNotNull(model, "model");

            ExceptionUtilities.Assert(
                payloadElement is ODataEntry || payloadElement is ODataFeed,
                "Can only determine entity type for entry or feed payloads.");

            ODataFeed feed = payloadElement as ODataFeed;

            if (feed != null)
            {
                // A feed doesn't know it's type. If it doesn't have any entries we can't determine the type.
                var feedentry = feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>().FirstOrDefault();
                if (feedentry != null)
                {
                    return(model.FindDeclaredType(feedentry.TypeName) as IEdmEntityType);
                }

                return(null);
            }

            ODataEntry entry = payloadElement as ODataEntry;

            if (entry != null)
            {
                return(model.FindDeclaredType(entry.TypeName) as IEdmEntityType);
            }

            return(null);
        }
예제 #4
0
        internal void WriteFeedNextPageLink(ODataFeed feed)
        {
            Uri nextPageLink = feed.NextPageLink;

            if (nextPageLink != null)
            {
                AtomFeedMetadata annotation   = feed.GetAnnotation <AtomFeedMetadata>();
                AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata((annotation == null) ? null : annotation.NextPageLink, "next", nextPageLink, null, null);
                this.atomFeedMetadataSerializer.WriteAtomLink(linkMetadata, null);
            }
        }
예제 #5
0
        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);
        }
        /// <summary>
        /// Writes a feed link.
        /// </summary>
        /// <param name="feed">The feed that contains the link.</param>
        /// <param name="relation">Relation attribute of the link.</param>
        /// <param name="href">href attribute of the link.</param>
        /// <param name="getLinkMetadata">Function to get the AtomLinkMetadata for the feed link.</param>
        internal void WriteFeedLink(ODataFeed feed, string relation, Uri href, Func <AtomFeedMetadata, AtomLinkMetadata> getLinkMetadata)
        {
            AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>();
            AtomLinkMetadata mergedLink   = ODataAtomWriterMetadataUtils.MergeLinkMetadata(
                getLinkMetadata(feedMetadata),
                relation,
                href,
                null,     /*title*/
                null /*mediaType*/);

            this.atomFeedMetadataSerializer.WriteAtomLink(mergedLink, null);
        }
예제 #7
0
        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);
        }
        private void ApplyFeedInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataFeed feed, ODataDeserializerReadContext readContext)
        {
            ODataFeedAnnotation feedAnnotation = feed.GetAnnotation <ODataFeedAnnotation>();

            Contract.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it.");

            IEdmEntityTypeReference elementType = ToEntityType(navigationProperty);

            foreach (ODataEntry entryInFeed in feedAnnotation)
            {
                object childEntityResource = CreateNestedEntityAndApplyProperties(entryInFeed, elementType, readContext);
                AddReferenceToCollection(entityResource, navigationProperty, childEntityResource);
            }
        }
예제 #9
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));
        }
예제 #10
0
        private void ApplyFeedInNavigationProperty(ResourceProperty navigationProperty, ResourceSetWrapper targetResourceSet, object entityResource, ODataFeed feed)
        {
            ODataFeedAnnotation annotation = feed.GetAnnotation <ODataFeedAnnotation>();

            if (base.Update && ((this.ContentFormat != ContentFormat.VerboseJson) || (annotation.Count > 0)))
            {
                throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_DeepUpdateNotSupported);
            }
            System.Data.Services.SegmentInfo segmentInfo = Deserializer.CreateSegment(navigationProperty, navigationProperty.Name, targetResourceSet, false);
            foreach (ODataEntry entry in annotation)
            {
                object resourceToBeAdded = this.CreateNestedEntityAndApplyProperties(segmentInfo, entry);
                base.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, resourceToBeAdded);
            }
        }
예제 #11
0
        private void WriteFeed(ODataWriter writer, ODataFeed feed)
        {
            writer.WriteStart(feed);
            var annotation = feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>();

            if (annotation != null)
            {
                foreach (var entry in annotation)
                {
                    this.WriteEntry(writer, entry);
                }
            }

            writer.WriteEnd();
        }
            /// <summary>
            /// Visits a feed item.
            /// </summary>
            /// <param name="feed">The feed item to visit.</param>
            /// <returns>An ODataPayloadElement representing the feed.</returns>
            protected override ODataPayloadElement VisitFeed(ODataFeed feed)
            {
                ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

                EntitySetInstance entitySet = (EntitySetInstance)base.VisitFeed(feed);

                var atomMetadata = feed.GetAnnotation <AtomFeedMetadata>();

                if (atomMetadata != null)
                {
                    ConvertAtomFeedMetadata(atomMetadata, entitySet);
                }

                return(entitySet);
            }
예제 #13
0
        /// <summary>
        /// Applies a feed which is the content of a navigation property to the specified entity resource.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for which the feed was specified.</param>
        /// <param name="targetResourceSet">The resource set of the target of the navigation property.</param>
        /// <param name="entityResource">The entity resource to apply the value to.</param>
        /// <param name="feed">The feed to apply.</param>
        /// <remarks>Note that the targetResourceSet will be filled for non-ATOM formats, but it will be null for ATOM.</remarks>
        private void ApplyFeedInNavigationProperty(
            ResourceProperty navigationProperty,
            ResourceSetWrapper targetResourceSet,
            object entityResource,
            ODataFeed feed)
        {
            Debug.Assert(
                navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType,
                "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType");
            Debug.Assert(
                navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference,
                "ODataLib reader should never report a feed for a singleton navigation property.");
            Debug.Assert(targetResourceSet != null, "targetResourceSet != null");
            Debug.Assert(entityResource != null, "entityResource != null");
            Debug.Assert(feed != null, "feed != null");

            ODataFeedAnnotation feedAnnotation = feed.GetAnnotation <ODataFeedAnnotation>();

            Debug.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it.");

            // Deep insert is not allowed in updates.
            // In JSON we must not fail due to deep updates if the feed is empty. In JSON empty array is reported as an empty feed
            // but there's no telling if it means empty deep update array or empty array of bindings.
            if (this.Update && (this.IsAtomRequest || feedAnnotation.Count > 0))
            {
                throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_DeepUpdateNotSupported);
            }

            Debug.Assert(targetResourceSet != null, "targetResourceSet != null");
            SegmentInfo propertySegmentInfo = CreateSegment(navigationProperty, navigationProperty.Name, targetResourceSet, false /* singleResult */);

            Debug.Assert(propertySegmentInfo.TargetKind != RequestTargetKind.OpenProperty, "Open navigation properties are not supported on OpenTypes.");
            Debug.Assert(
                propertySegmentInfo.TargetSource == RequestTargetSource.Property &&
                propertySegmentInfo.TargetKind == RequestTargetKind.Resource &&
                propertySegmentInfo.SingleResult == false,
                "Must be navigation set property.");

            // Look through the entries in the feed.
            foreach (ODataEntry entryInFeed in feedAnnotation)
            {
                // For each entry create the corresponding entity resource.
                object childEntityResource = this.CreateNestedEntityAndApplyProperties(propertySegmentInfo, entryInFeed);
                Debug.Assert(childEntityResource != null, "Non top-level entries should never produce null entity resource.");

                this.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, childEntityResource);
            }
        }
예제 #14
0
        internal void WriteFeedMetadata(ODataFeed feed, string updatedTime, out bool authorWritten)
        {
            AtomFeedMetadata annotation = feed.GetAnnotation <AtomFeedMetadata>();

            if (annotation == null)
            {
                base.WriteElementWithTextContent("", "id", "http://www.w3.org/2005/Atom", feed.Id);
                base.WriteEmptyElement("", "title", "http://www.w3.org/2005/Atom");
                base.WriteElementWithTextContent("", "updated", "http://www.w3.org/2005/Atom", updatedTime);
                authorWritten = false;
            }
            else
            {
                this.atomFeedMetadataSerializer.WriteFeedMetadata(annotation, feed, updatedTime, out authorWritten);
            }
        }
예제 #15
0
        private void ApplyFeedInNavigationProperty(IEdmNavigationProperty navigationProperty, object entityResource, ODataFeed feed, ODataDeserializerContext readContext)
        {
            ODataFeedAnnotation feedAnnotation = feed.GetAnnotation <ODataFeedAnnotation>();

            Contract.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it.");

            ODataEntryDeserializer deserializer = DeserializerProvider.GetODataDeserializer(navigationProperty.Type);
            object value = deserializer.ReadInline(feed, readContext);

            if (readContext.IsPatchMode)
            {
                throw Error.InvalidOperation(SRResources.CannotPatchNavigationProperties, navigationProperty.Name, navigationProperty.DeclaringEntityType().FullName());
            }

            SetProperty(entityResource, navigationProperty.Name, isDelta: false, value: value);
        }
예제 #16
0
        private void WriteFeed(ODataWriter writer, Lazy <ODataReader> lazyReader, ODataFeed feed)
        {
            this.WriteStart(writer, feed);
            var annotation = feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>();

            if (annotation != null)
            {
                int count = annotation.Count;
                for (int i = 0; i < count; ++i)
                {
                    this.WriteEntry(writer, lazyReader, annotation[i]);
                }
            }

            this.WriteEnd(writer, ODataReaderState.FeedEnd);
            this.Read(lazyReader);
        }
예제 #17
0
        /// <summary>
        /// Write the given feed metadata in atom format
        /// </summary>
        /// <param name="feed">The feed for which to write the meadata or null if it is the metadata of an atom:source element.</param>
        /// <param name="updatedTime">Value for the atom:updated element.</param>
        /// <param name="authorWritten">Set to true if the author element was written, false otherwise.</param>
        internal void WriteFeedMetadata(ODataFeed feed, string updatedTime, out bool authorWritten)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feed != null, "feed != null");
            Debug.Assert(!string.IsNullOrEmpty(updatedTime), "!string.IsNullOrEmpty(updatedTime)");
#if DEBUG
            DateTimeOffset tempDateTimeOffset;
            Debug.Assert(DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset), "DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset)");
#endif

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

            if (feedMetadata == null)
            {
                // create the required metadata elements with default values.

                // <atom:id>idValue</atom:id>
                Debug.Assert(!string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now.");
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomIdElementName,
                    AtomConstants.AtomNamespace,
                    feed.Id);

                // <atom:title></atom:title>
                this.WriteEmptyElement(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomTitleElementName,
                    AtomConstants.AtomNamespace);

                // <atom:updated>dateTimeOffset</atom:updated>
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomUpdatedElementName,
                    AtomConstants.AtomNamespace,
                    updatedTime);

                authorWritten = false;
            }
            else
            {
                this.atomFeedMetadataSerializer.WriteFeedMetadata(feedMetadata, feed, updatedTime, out authorWritten);
            }
        }
예제 #18
0
        /// <summary>
        /// Writes the next page link for a feed.
        /// </summary>
        /// <param name="feed">The feed to write the next page link for.</param>
        internal void WriteFeedNextPageLink(ODataFeed feed)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feed != null, "feed != null");

            Uri nextPageLink = feed.NextPageLink;

            if (nextPageLink != null)
            {
                // <atom:link rel="next" href="next-page-link" />
                AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>();
                AtomLinkMetadata mergedLink   = ODataAtomWriterMetadataUtils.MergeLinkMetadata(
                    feedMetadata == null ? null : feedMetadata.NextPageLink,
                    AtomConstants.AtomNextRelationAttributeValue,
                    nextPageLink,
                    null, /*title*/
                    null /*mediaType*/);
                this.atomFeedMetadataSerializer.WriteAtomLink(mergedLink, null);
            }
        }
        /// <summary>
        /// Write the ATOM metadata for a feed
        /// </summary>
        /// <param name="writer">The Xml writer to write to.</param>
        /// <param name="baseUri">The base Uri of the document or null if none was specified.</param>
        /// <param name="feed">The feed for which to write the metadata.</param>
        internal static void WriteFeedMetadata(XmlWriter writer, Uri baseUri, ODataFeed feed)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(feed != null, "feed != null");

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

            if (feedMetadata == null)
            {
                // create the required metadata elements with default values.

                // <atom:id>idValue</atom:id>
                Debug.Assert(!string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now.");
                ODataAtomWriterUtils.WriteElementWithTextContent(
                    writer,
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomIdElementName,
                    AtomConstants.AtomNamespace,
                    feed.Id);

                // <atom:title></atom:title>
                ODataAtomWriterUtils.WriteEmptyElement(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace);

                // <atom:updated>dateTimeOffset</atom:updated>
                ODataAtomWriterUtils.WriteElementWithTextContent(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(DateTimeOffset.UtcNow));
            }
            else
            {
                WriteFeedMetadata(writer, baseUri, feedMetadata, feed);
            }
        }
예제 #20
0
        /// <summary>
        /// Gets the materializer feed.
        /// </summary>
        /// <param name="feed">The feed.</param>
        /// <returns>The materializer feed.</returns>
        public static MaterializerFeed GetFeed(ODataFeed feed)
        {
            IEnumerable <ODataEntry> entries = feed.GetAnnotation <IEnumerable <ODataEntry> >();

            return(new MaterializerFeed(feed, entries));
        }
예제 #21
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);
        }
            /// <summary>
            /// Visits a feed item.
            /// </summary>
            /// <param name="feed">The feed to visit.</param>
            protected override ODataPayloadElement VisitFeed(ODataFeed feed)
            {
                ODataPayloadElement payloadElement = base.VisitFeed(feed);
                ODataFeedPayloadOrderObjectModelAnnotation payloadOrderFeedAnnotation = feed.GetAnnotation <ODataFeedPayloadOrderObjectModelAnnotation>();

                if (payloadOrderFeedAnnotation != null)
                {
                    PayloadOrderODataPayloadElementAnnotation payloadOrderElementAnnotation = new PayloadOrderODataPayloadElementAnnotation();
                    payloadOrderElementAnnotation.PayloadItems.AddRange(payloadOrderFeedAnnotation.PayloadItems);
                    payloadElement.Add(payloadOrderElementAnnotation);
                }

                return(payloadElement);
            }
 /// <summary>
 /// Writes a feed link.
 /// </summary>
 /// <param name="feed">The feed that contains the link.</param>
 /// <param name="relation">Relation attribute of the link.</param>
 /// <param name="href">href attribute of the link.</param>
 /// <param name="getLinkMetadata">Function to get the AtomLinkMetadata for the feed link.</param>
 internal void WriteFeedLink(ODataFeed feed, string relation, Uri href, Func<AtomFeedMetadata, AtomLinkMetadata> getLinkMetadata)
 {
     AtomFeedMetadata feedMetadata = feed.GetAnnotation<AtomFeedMetadata>();
     AtomLinkMetadata mergedLink = ODataAtomWriterMetadataUtils.MergeLinkMetadata(
             getLinkMetadata(feedMetadata),
             relation,
             href,
             null, /*title*/
             null /*mediaType*/);
     this.atomFeedMetadataSerializer.WriteAtomLink(mergedLink, null);
 }
예제 #24
0
        public static AtomFeedMetadata Atom(this ODataFeed feed)
        {
            ExceptionUtils.CheckArgumentNotNull(feed, "feed");

            return(feed.GetAnnotation <AtomFeedMetadata>());
        }
 /// <summary>
 /// Visits a feed item.
 /// </summary>
 /// <param name="feed">The feed to visit.</param>
 protected override void VisitFeed(ODataFeed feed)
 {
     this.VisitAtomMetadata(feed.GetAnnotation <AtomFeedMetadata>());
     base.VisitFeed(feed);
 }
예제 #26
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();
        }
예제 #27
0
 /// <summary>
 /// Gets all entries attached to the <paramref name="feed"/> via the
 /// <see cref="ODataFeedEntriesObjectModelAnnotation"/> annotation.
 /// </summary>
 /// <param name="feed">The <see cref="ODataFeed"/> to get the entries for.</param>
 /// <returns>A list of entries or null if none were found.</returns>
 public static IList <ODataEntry> Entries(this ODataFeed feed)
 {
     ExceptionUtilities.CheckArgumentNotNull(feed, "feed");
     return(feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>());
 }
예제 #28
0
        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);
        }
        /// <summary>
        /// Write the given feed metadata in atom format
        /// </summary>
        /// <param name="feed">The feed for which to write the meadata or null if it is the metadata of an atom:source element.</param>
        /// <param name="updatedTime">Value for the atom:updated element.</param>
        /// <param name="authorWritten">Set to true if the author element was written, false otherwise.</param>
        internal void WriteFeedMetadata(ODataFeed feed, string updatedTime, out bool authorWritten)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feed != null, "feed != null");
            Debug.Assert(!string.IsNullOrEmpty(updatedTime), "!string.IsNullOrEmpty(updatedTime)");
#if DEBUG
            DateTimeOffset tempDateTimeOffset;
            Debug.Assert(DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset), "DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset)");
#endif

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

            if (feedMetadata == null)
            {
                // create the required metadata elements with default values.

                // <atom:id>idValue</atom:id>
                Debug.Assert(!string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now.");
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomIdElementName,
                    AtomConstants.AtomNamespace,
                    feed.Id);

                // <atom:title></atom:title>
                this.WriteEmptyElement(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomTitleElementName,
                    AtomConstants.AtomNamespace);

                // <atom:updated>dateTimeOffset</atom:updated>
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomUpdatedElementName,
                    AtomConstants.AtomNamespace,
                    updatedTime);

                authorWritten = false;
            }
            else
            {
                this.atomFeedMetadataSerializer.WriteFeedMetadata(feedMetadata, feed, updatedTime, out authorWritten);
            }
        }
예제 #30
0
 public static MaterializerFeed GetFeed(ODataFeed feed)
 {
     return(new MaterializerFeed(feed, feed.GetAnnotation <IEnumerable <ODataEntry> >()));
 }
        /// <summary>
        /// Writes the next page link for a feed.
        /// </summary>
        /// <param name="feed">The feed to write the next page link for.</param>
        internal void WriteFeedNextPageLink(ODataFeed feed)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feed != null, "feed != null");

            Uri nextPageLink = feed.NextPageLink;
            if (nextPageLink != null)
            {
                // <atom:link rel="next" href="next-page-link" />
                AtomFeedMetadata feedMetadata = feed.GetAnnotation<AtomFeedMetadata>();
                AtomLinkMetadata mergedLink = ODataAtomWriterMetadataUtils.MergeLinkMetadata(
                    feedMetadata == null ? null : feedMetadata.NextPageLink,
                    AtomConstants.AtomNextRelationAttributeValue,
                    nextPageLink,
                    null, /*title*/
                    null /*mediaType*/);
                this.atomFeedMetadataSerializer.WriteAtomLink(mergedLink, null);
            }
        }
예제 #32
0
        /// <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);
        }