public override object ReadInline(ODataFeed feed, ODataDeserializerContext readContext) { if (readContext == null) { throw Error.ArgumentNull("readContext"); } if (feed == null) { return(null); } ODataEntryDeserializer deserializer = DeserializerProvider.GetODataDeserializer(_edmEntityType); IList feedValue = CreateNewCollection(EdmLibHelpers.GetClrType(_edmEntityType, EdmModel)); ODataFeedAnnotation feedAnnotation = feed.GetAnnotation <ODataFeedAnnotation>(); Contract.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it."); foreach (ODataEntry entry in feedAnnotation) { ODataEntryAnnotation annotation = entry.GetAnnotation <ODataEntryAnnotation>(); Contract.Assert(annotation != null); feedValue.Add(deserializer.ReadInline(entry, readContext)); } return(feedValue); }
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); } }
private IEnumerable ReadItems(ODataFeed feed, ODataDeserializerContext readContext) { ODataEntryDeserializer deserializer = DeserializerProvider.GetODataDeserializer(_edmEntityType); ODataFeedAnnotation feedAnnotation = feed.GetAnnotation<ODataFeedAnnotation>(); Contract.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it."); foreach (ODataEntry entry in feedAnnotation) { ODataEntryAnnotation annotation = entry.GetAnnotation<ODataEntryAnnotation>(); Contract.Assert(annotation != null); yield return deserializer.ReadInline(entry, readContext); } }
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); } }
/// <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); } }
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); }
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> /// 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); }