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