private void ApplyNavigationProperty(ODataNavigationLink navigationLink, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, ResourceProperty navigationProperty, object entityResource) { ResourceSetWrapper targetResourceSet = null; targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty); foreach (ODataItem item in navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>()) { ODataEntityReferenceLink entityReferenceLink = item as ODataEntityReferenceLink; if (entityReferenceLink != null) { this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink); } else { ODataFeed feed = item as ODataFeed; if (feed != null) { this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed); } else { ODataEntry entry = (ODataEntry)item; this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry); } } } }
private void WriteNavigationLink(ODataWriter writer, Lazy <ODataReader> lazyReader, ODataNavigationLink link) { this.WriteStart(writer, link); var expanded = link.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (expanded != null) { var feed = expanded.ExpandedItem as ODataFeed; if (feed != null) { this.WriteFeed(writer, lazyReader, feed); } else { ODataEntry entry = expanded.ExpandedItem as ODataEntry; if (entry != null || expanded.ExpandedItem == null) { this.WriteEntry(writer, lazyReader, entry); } else { ExceptionUtilities.Assert(expanded.ExpandedItem is ODataEntityReferenceLink, "Content of a nav. link can only be a feed, entry or entity reference link."); writer.WriteEntityReferenceLink((ODataEntityReferenceLink)expanded.ExpandedItem); } } } this.WriteEnd(writer, ODataReaderState.NavigationLinkEnd); this.Read(lazyReader); }
private void ApplyNavigationProperty(ODataNavigationLink navigationLink, IEdmNavigationProperty navigationProperty, object entityResource, ODataDeserializerContext readContext) { ODataNavigationLinkAnnotation navigationLinkAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Contract.Assert(navigationLinkAnnotation != null, "navigationLinkAnnotation != null"); Contract.Assert(navigationLink.IsCollection.HasValue, "We should know the cardinality of the navigation link by now."); foreach (ODataItem childItem in navigationLinkAnnotation) { ODataEntityReferenceLink entityReferenceLink = childItem as ODataEntityReferenceLink; if (entityReferenceLink != null) { // ignore links. continue; } ODataFeed feed = childItem as ODataFeed; if (feed != null) { ApplyFeedInNavigationProperty(navigationProperty, entityResource, feed, readContext); continue; } // It must be entry by now. ODataEntry entry = (ODataEntry)childItem; if (entry != null) { ApplyEntryInNavigationProperty(navigationProperty, entityResource, entry, readContext); } } }
/// <summary> /// Writes the navigation link's start element and atom metadata. /// </summary> /// <param name="navigationLink">The navigation link to write.</param> /// <param name="navigationLinkUrlOverride">Url to use for the navigation link. If this is specified the Url property on the <paramref name="navigationLink"/> /// will be ignored. If this parameter is null, the Url from the navigation link is used.</param> internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride) { Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name was not verified yet."); Debug.Assert(navigationLink.Url != null, "The navigation link Url was not verified yet."); Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue"); if (navigationLink.AssociationLinkUrl != null) { // TODO:Association Link - Add back support for customizing association link element in Atom this.WriteAssociationLink(navigationLink.Name, navigationLink.AssociationLinkUrl, null); } // <atom:link> this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace); string linkRelation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink); string linkType = AtomUtils.ComputeODataNavigationLinkType(navigationLink); string linkTitle = navigationLink.Name; Uri navigationLinkUrl = navigationLinkUrlOverride ?? navigationLink.Url; AtomLinkMetadata linkMetadata = navigationLink.GetAnnotation <AtomLinkMetadata>(); AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, navigationLinkUrl, linkTitle, linkType); this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(mergedMetadata, null /* etag */); }
/// <summary> /// Creates the materializer link with a feed. /// </summary> /// <param name="link">The link.</param> /// <param name="feed">The feed.</param> /// <returns>The materializer link.</returns> public static MaterializerNavigationLink CreateLink(ODataNavigationLink link, ODataFeed feed) { Debug.Assert(link.GetAnnotation <MaterializerNavigationLink>() == null, "there should be no MaterializerNavigationLink annotation on the feed link yet"); MaterializerNavigationLink materializedNavigationLink = new MaterializerNavigationLink(link, feed); link.SetAnnotation <MaterializerNavigationLink>(materializedNavigationLink); return(materializedNavigationLink); }
/// <summary> /// Applies a navigation link as a navigation property. /// </summary> /// <param name="navigationLink">The navigation link read from the payload to apply.</param> /// <param name="entityResourceSet">The resource set into which the entity belongs to.</param> /// <param name="entityResourceType">The type of the entity to apply the properties to.</param> /// <param name="navigationProperty">The navigation property which coresponds with the navigation link.</param> /// <param name="entityResource">The entity resource to apply the properties to.</param> private void ApplyNavigationProperty( ODataNavigationLink navigationLink, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, ResourceProperty navigationProperty, object entityResource) { Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert(entityResourceSet != null, "entityResourceSet != null"); Debug.Assert(entityResourceType != null, "entityResourceType != null"); Debug.Assert(entityResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "Only entity types can be specified for entities."); Debug.Assert(navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType"); Debug.Assert(navigationLink.Name == navigationProperty.Name, "The navigationProperty must have the same name as the navigationLink to apply."); Debug.Assert(entityResource != null, "entityResource != null"); ResourceSetWrapper targetResourceSet = null; // Get the target resource set for the navigation property, this also causes validation of the resource set and thus migth fail. // WCF DS Used to do this in ATOM only if the link was expanded, which was a security issue we decided to fix, so now we do it always. targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty); ODataNavigationLinkAnnotation navigationLinkAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(navigationLinkAnnotation != null, "navigationLinkAnnotation != null"); Debug.Assert(navigationLinkAnnotation.Count > 0, "Each navigation link must have at least one child in request."); Debug.Assert(navigationLink.IsCollection.HasValue, "We should know the cardinality of the navigation link by now."); // We have to allow IsCollection=false for ResourceSetReference properties as well. Debug.Assert( navigationLink.IsCollection == true || (navigationLinkAnnotation.Count == 1), "If the navigation link is a singleton, then there must be exactly one child in it and the property must be a singleton as well."); Debug.Assert( navigationLink.IsCollection == false || (navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference), "If the navigation link is a collection, then the property must be a collection as well."); // Just loop through the navigation link content // Note that if the navigation link is a singleton it must have just one item in it, so it's OK to loop anyway. foreach (ODataItem childItem in navigationLinkAnnotation) { ODataEntityReferenceLink entityReferenceLink = childItem as ODataEntityReferenceLink; if (entityReferenceLink != null) { this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink); continue; } ODataFeed feed = childItem as ODataFeed; if (feed != null) { this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed); continue; } // It must be entry by now. ODataEntry entry = (ODataEntry)childItem; this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry); } }
public static AtomLinkMetadata Atom(this ODataNavigationLink navigationLink) { ExceptionUtils.CheckArgumentNotNull <ODataNavigationLink>(navigationLink, "navigationLink"); AtomLinkMetadata annotation = navigationLink.GetAnnotation <AtomLinkMetadata>(); if (annotation == null) { annotation = new AtomLinkMetadata(); navigationLink.SetAnnotation <AtomLinkMetadata>(annotation); } return(annotation); }
public static AtomLinkMetadata Atom(this ODataNavigationLink navigationLink) { ExceptionUtils.CheckArgumentNotNull(navigationLink, "navigationLink"); AtomLinkMetadata linkMetadata = navigationLink.GetAnnotation <AtomLinkMetadata>(); if (linkMetadata == null) { linkMetadata = new AtomLinkMetadata(); navigationLink.SetAnnotation(linkMetadata); } return(linkMetadata); }
/// <summary> /// Gets the expanded content of a navigation link. /// </summary> /// <param name="navigationLink">The <see cref="ODataNavigationLink"/> to get the navigation content for.</param> /// <param name="expandedContent">The expanded content (if the method returns null), which can be either /// null (null expanded entry), or <see cref="ODataEntry"/> or <see cref="ODataFeed"/>.</param> /// <returns>true if the <paramref name="navigationLink"/> is expanded, or false otherwise.</returns> public static bool TryGetExpandedContent(this ODataNavigationLink navigationLink, out object expandedContent) { ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink"); var expandedItemAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (expandedItemAnnotation != null) { expandedContent = expandedItemAnnotation.ExpandedItem; return(true); } else { expandedContent = null; return(false); } }
/// <summary> /// Visits a navigation link item. /// </summary> /// <param name="navigationLink">The navigation link to visit.</param> /// <returns>An ODataPayloadElement representing the navigation link.</returns> protected override ODataPayloadElement VisitNavigationLink(ODataNavigationLink navigationLink) { ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink"); NavigationPropertyInstance navigationProperty = (NavigationPropertyInstance)base.VisitNavigationLink(navigationLink); // In ATOM even deferred links may know if they point to collection or singleton. // So add the content type annotation to them (through it IsCollection) so that comparison is precise. DeferredLink deferredLink = navigationProperty.Value as DeferredLink; if (deferredLink != null && navigationLink.IsCollection.HasValue) { deferredLink.IsCollection(navigationLink.IsCollection.Value); } AtomLinkMetadata atomMetadata = navigationLink.GetAnnotation <AtomLinkMetadata>(); if (atomMetadata != null && deferredLink != null) { ConvertAtomLinkChildrenMetadata(atomMetadata, navigationProperty.Value); } return(navigationProperty); }
/// <summary> /// Writes the navigation link's start element and atom metadata. /// </summary> /// <param name="navigationLink">The navigation link to write.</param> /// <param name="navigationLinkUrlOverride">Url to use for the navigation link. If this is specified the Url property on the <paramref name="navigationLink"/> /// will be ignored. If this parameter is null, the Url from the navigation link is used.</param> internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name was not verified yet."); Debug.Assert(navigationLink.Url != null, "The navigation link Url was not verified yet."); Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue"); // <atom:link> this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace); string linkRelation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink); string linkType = AtomUtils.ComputeODataNavigationLinkType(navigationLink); string linkTitle = navigationLink.Name; Uri navigationLinkUrl = navigationLinkUrlOverride ?? navigationLink.Url; AtomLinkMetadata linkMetadata = navigationLink.GetAnnotation<AtomLinkMetadata>(); AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, navigationLinkUrl, linkTitle, linkType); this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(mergedMetadata, null /* etag */); }
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); }
internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride) { base.XmlWriter.WriteStartElement("", "link", "http://www.w3.org/2005/Atom"); string relation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink); string mediaType = AtomUtils.ComputeODataNavigationLinkType(navigationLink); string name = navigationLink.Name; Uri href = navigationLinkUrlOverride ?? navigationLink.Url; AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(navigationLink.GetAnnotation <AtomLinkMetadata>(), relation, href, name, mediaType); this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(linkMetadata, null); }
public static MaterializerNavigationLink GetLink(ODataNavigationLink link) { return(link.GetAnnotation <MaterializerNavigationLink>()); }
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> /// Reads an entry from the <paramref name="odataReader"/> and all it's children including expanded entries and feeds. /// </summary> /// <param name="odataReader">The ODataReader to read from.</param> /// <param name="topLevelSegmentInfo">The segment info for the top-level entry to read.</param> /// <returns>The <see cref="ODataEntry"/> with annotations which store the navigation links and their expanded values.</returns> private ODataEntry ReadEntry(ODataReader odataReader, SegmentInfo topLevelSegmentInfo) { Debug.Assert(odataReader != null, "odataReader != null"); Debug.Assert(odataReader.State == ODataReaderState.Start, "The ODataReader must not have been used yet."); Debug.Assert(topLevelSegmentInfo != null, "topLevelSegmentInfo != null"); ODataEntry topLevelEntry = null; Stack <ODataItem> itemsStack = new Stack <ODataItem>(); while (odataReader.Read()) { // Don't let the item stack grow larger than we can process later. Also lets us to fail and report the recursion depth limit error before ODL does. if (itemsStack.Count >= RecursionLimit) { throw DataServiceException.CreateDeepRecursion(RecursionLimit); } switch (odataReader.State) { case ODataReaderState.EntryStart: ODataEntry entry = (ODataEntry)odataReader.Item; ODataEntryAnnotation entryAnnotation = null; if (entry != null) { entryAnnotation = new ODataEntryAnnotation(); entry.SetAnnotation(entryAnnotation); } if (itemsStack.Count == 0) { Debug.Assert(entry != null, "The top-level entry can never be null."); topLevelEntry = entry; // For top-level entry, create the entry resource here. // This is needed since the creation of the resource may fail (especially if this is an update in which case // we evaluate the URL query, which may return no results and thus we would fail with 404) // and we need to report that failure rather then potential other failures caused by the properties in the entry in question. this.CreateEntityResource(topLevelSegmentInfo, entry, entryAnnotation, /*topLevel*/ true); } else { ODataItem parentItem = itemsStack.Peek(); ODataFeed parentFeed = parentItem as ODataFeed; if (parentFeed != null) { ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>(); Debug.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it."); parentFeedAnnotation.Add(entry); } else { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)parentItem; ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Debug.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child."); Debug.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child."); parentNavigationLinkAnnotation.Add(entry); } } itemsStack.Push(entry); break; case ODataReaderState.EntryEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.NavigationLinkStart: ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item; Debug.Assert(navigationLink != null, "Navigation link should never be null."); navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation()); Debug.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item."); { ODataEntry parentEntry = (ODataEntry)itemsStack.Peek(); ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>(); Debug.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the navigation link annotation on it."); parentEntryAnnotation.Add(navigationLink); } itemsStack.Push(navigationLink); break; case ODataReaderState.NavigationLinkEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.FeedStart: ODataFeed feed = (ODataFeed)odataReader.Item; Debug.Assert(feed != null, "Feed should never be null."); feed.SetAnnotation(new ODataFeedAnnotation()); Debug.Assert(itemsStack.Count > 0, "Since we always start reading entry, we should never get a feed as the top-level item."); { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); Debug.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child."); parentNavigationLinkAnnotation.Add(feed); } itemsStack.Push(feed); break; case ODataReaderState.FeedEnd: Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack."); itemsStack.Pop(); break; case ODataReaderState.EntityReferenceLink: ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item; Debug.Assert(entityReferenceLink != null, "Entity reference link should never be null."); Debug.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item."); { ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek(); ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>(); Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it."); parentNavigationLinkAnnotation.Add(entityReferenceLink); } break; default: Debug.Assert(false, "We should never get here, it means the ODataReader reported a wrong state."); break; } } Debug.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now."); Debug.Assert(topLevelEntry != null, "A top level entry should have been read by now."); return(topLevelEntry); }
private ODataEntry ReadEntry(ODataReader odataReader, System.Data.Services.SegmentInfo topLevelSegmentInfo) { ODataEntry entry = null; Stack <ODataItem> stack = new Stack <ODataItem>(); while (odataReader.Read()) { if (stack.Count >= 100) { throw DataServiceException.CreateDeepRecursion(100); } switch (odataReader.State) { case ODataReaderState.FeedStart: { ODataFeed feed2 = (ODataFeed)odataReader.Item; feed2.SetAnnotation <ODataFeedAnnotation>(new ODataFeedAnnotation()); ODataNavigationLink link3 = (ODataNavigationLink)stack.Peek(); link3.GetAnnotation <ODataNavigationLinkAnnotation>().Add(feed2); stack.Push(feed2); break; } case ODataReaderState.FeedEnd: stack.Pop(); break; case ODataReaderState.EntryStart: { ODataEntry entry2 = (ODataEntry)odataReader.Item; ODataEntryAnnotation annotation = null; if (entry2 != null) { annotation = new ODataEntryAnnotation(); entry2.SetAnnotation <ODataEntryAnnotation>(annotation); } if (stack.Count == 0) { entry = entry2; this.CreateEntityResource(topLevelSegmentInfo, entry2, annotation, true); } else { ODataItem item = stack.Peek(); ODataFeed feed = item as ODataFeed; if (feed != null) { feed.GetAnnotation <ODataFeedAnnotation>().Add(entry2); } else { ODataNavigationLink link = (ODataNavigationLink)item; link.GetAnnotation <ODataNavigationLinkAnnotation>().Add(entry2); } } stack.Push(entry2); break; } case ODataReaderState.EntryEnd: stack.Pop(); break; case ODataReaderState.NavigationLinkStart: { ODataNavigationLink link2 = (ODataNavigationLink)odataReader.Item; link2.SetAnnotation <ODataNavigationLinkAnnotation>(new ODataNavigationLinkAnnotation()); ODataEntry entry3 = (ODataEntry)stack.Peek(); entry3.GetAnnotation <ODataEntryAnnotation>().Add(link2); stack.Push(link2); break; } case ODataReaderState.NavigationLinkEnd: stack.Pop(); break; case ODataReaderState.EntityReferenceLink: { ODataEntityReferenceLink link4 = (ODataEntityReferenceLink)odataReader.Item; ODataNavigationLink link5 = (ODataNavigationLink)stack.Peek(); link5.GetAnnotation <ODataNavigationLinkAnnotation>().Add(link4); break; } } } return(entry); }
/// <summary> /// Visits a navigation link item. /// </summary> /// <param name="navigationLink">The navigation link to visit.</param> protected override ODataPayloadElement VisitNavigationLink(ODataNavigationLink navigationLink) { ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink"); ODataPayloadElement navigationPropertyContent = null; // check whether there is an entry or feed associated with the link var expandedItemAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>(); if (expandedItemAnnotation != null) { string navigationLinkUrlString = !this.payloadContainsIdentityMetadata || navigationLink.Url == null ? null : navigationLink.Url.OriginalString; if (expandedItemAnnotation.ExpandedItem is ODataEntry) { navigationPropertyContent = new ExpandedLink(this.Visit((ODataEntry)expandedItemAnnotation.ExpandedItem)) { UriString = navigationLinkUrlString }; } else if (expandedItemAnnotation.ExpandedItem is ODataFeed) { navigationPropertyContent = new ExpandedLink(this.Visit((ODataFeed)expandedItemAnnotation.ExpandedItem)) { UriString = navigationLinkUrlString }; } else if (expandedItemAnnotation.ExpandedItem is ODataEntityReferenceLink) { ExceptionUtilities.Assert(!this.response, "Entity reference links in navigation links can only appear in requests."); navigationPropertyContent = this.VisitEntityReferenceLink((ODataEntityReferenceLink)expandedItemAnnotation.ExpandedItem); } else if (expandedItemAnnotation.ExpandedItem is List <ODataItem> ) { ExceptionUtilities.Assert(!this.response, "Navigation links with multiple items in content can only appear in requests."); LinkCollection linkCollection = new LinkCollection(); foreach (ODataItem item in (List <ODataItem>)expandedItemAnnotation.ExpandedItem) { if (item is ODataFeed) { linkCollection.Add(new ExpandedLink(this.Visit((ODataFeed)item))); } else { ExceptionUtilities.Assert(item is ODataEntityReferenceLink, "Only feed and entity reference links can appear in navigation link content with multiple items."); linkCollection.Add(this.VisitEntityReferenceLink((ODataEntityReferenceLink)item)); } } navigationPropertyContent = linkCollection; } else { ExceptionUtilities.Assert(expandedItemAnnotation.ExpandedItem == null, "Only expanded entry, feed or null is allowed."); navigationPropertyContent = new ExpandedLink(new EntityInstance(null, true)) { UriString = navigationLinkUrlString }; } } else { ExceptionUtilities.Assert(this.response, "Deferred links are only valid in responses."); // this is a deferred link DeferredLink deferredLink = new DeferredLink() { UriString = !this.payloadContainsIdentityMetadata || navigationLink.Url == null ? null : navigationLink.Url.OriginalString, }; navigationPropertyContent = deferredLink; } DeferredLink associationLink = null; if (this.payloadContainsIdentityMetadata && navigationLink.AssociationLinkUrl != null) { associationLink = new DeferredLink() { UriString = navigationLink.AssociationLinkUrl.OriginalString }; } return(new NavigationPropertyInstance(navigationLink.Name, navigationPropertyContent, associationLink)); }
/// <summary> /// Visits a navigation link item. /// </summary> /// <param name="navigationLink">The navigation link to visit.</param> protected override void VisitNavigationLink(ODataNavigationLink navigationLink) { this.VisitAtomMetadata(navigationLink.GetAnnotation <AtomLinkMetadata>()); base.VisitNavigationLink(navigationLink); }