Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support writing nested delta resource sets with non-delta writer. #2250

Merged
merged 3 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 17 additions & 17 deletions src/Microsoft.OData.Core/JsonLight/ODataJsonLightWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,6 @@ protected override void EndDeltaResourceSet(ODataDeltaResourceSet deltaResourceS
protected override void StartDeletedResource(ODataDeletedResource resource)
{
Debug.Assert(resource != null, "resource != null");
Debug.Assert(!this.IsTopLevel, "Delta resource cannot be on top level.");
DeletedResourceScope resourceScope = this.CurrentDeletedResourceScope;
Debug.Assert(resourceScope != null, "Writing deleted entry and scope is not DeltaResourceScope");
ODataNestedResourceInfo parentNavLink = this.ParentNestedResourceInfo;
Expand All @@ -811,7 +810,7 @@ protected override void StartDeletedResource(ODataDeletedResource resource)
{
// Writing a deleted resource within an entity set
DeltaResourceSetScope deltaResourceSetScope = this.ParentScope as DeltaResourceSetScope;
Debug.Assert(deltaResourceSetScope != null, "Writing child of delta set and parent scope is not DeltaResourceSetScope");
Debug.Assert(this.ParentScope.State == WriterState.Start || deltaResourceSetScope != null, "Writing child of delta set and parent scope is not DeltaResourceSetScope");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we also update the error sentence to refresh the changes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the error text is still valid (and even more correct than previously). Previously the assert only checked that the parent scope was a delta resource set scope, not that what was being written was being written as the child of a delta set. The new assert validates that either the parent is scope is a deltaResourceSetScope or we're not attempting to write a child of a delta set (i.e., if the current state is start then we're writing at the top level, not as a child of a delta set.)


this.jsonWriter.StartObjectScope();

Expand All @@ -820,28 +819,28 @@ protected override void StartDeletedResource(ODataDeletedResource resource)
// Write ContextUrl
this.jsonLightResourceSerializer.WriteDeltaContextUri(
this.CurrentDeletedResourceScope.GetOrCreateTypeContext(this.writingResponse),
ODataDeltaKind.DeletedEntry, deltaResourceSetScope.ContextUriInfo);
ODataDeltaKind.DeletedEntry, deltaResourceSetScope?.ContextUriInfo);
this.WriteV4DeletedEntryContents(resource);
}
else
{
// Only write ContextUrl for V4.01 deleted resource if it is in a top level delta
// resource set and comes from a different entity set
string expectedNavigationSource =
deltaResourceSetScope.NavigationSource == null ? null : deltaResourceSetScope.NavigationSource.Name;
deltaResourceSetScope?.NavigationSource == null ? null : deltaResourceSetScope.NavigationSource.Name;
string currentNavigationSource =
resource.SerializationInfo != null ? resource.SerializationInfo.NavigationSourceName :
resourceScope.NavigationSource == null ? null : resourceScope.NavigationSource.Name;
resourceScope.NavigationSource?.Name;

if (String.IsNullOrEmpty(currentNavigationSource) || currentNavigationSource != expectedNavigationSource)
{
Debug.Assert(this.ScopeLevel == 3, "Writing a nested deleted resource of the wrong type should already have been caught.");
Debug.Assert(this.ScopeLevel <= 3, "Writing a nested deleted resource of the wrong type should already have been caught.");

// We are writing a deleted resource in a top level delta resource set
// from a different entity set, so include the context Url
this.jsonLightResourceSerializer.WriteDeltaContextUri(
this.CurrentDeletedResourceScope.GetOrCreateTypeContext(this.writingResponse),
ODataDeltaKind.DeletedEntry, deltaResourceSetScope.ContextUriInfo);
ODataDeltaKind.DeletedEntry, deltaResourceSetScope?.ContextUriInfo);
}

this.WriteDeletedEntryContents(resource);
Expand Down Expand Up @@ -1292,7 +1291,8 @@ protected override ResourceScope CreateResourceScope(ODataResource resource, IEd
/// <returns>The newly created JSON Light nested resource info scope.</returns>
protected override NestedResourceInfoScope CreateNestedResourceInfoScope(WriterState writerState, ODataNestedResourceInfo navLink, IEdmNavigationSource navigationSource, IEdmType itemType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
{
return new JsonLightNestedResourceInfoScope(writerState, navLink, navigationSource, itemType, skipWriting, selectedProperties, odataUri);
Debug.Assert(this.CurrentScope != null, "Creating a nested resource info scope with a null parent scope.");
return new JsonLightNestedResourceInfoScope(writerState, navLink, navigationSource, itemType, skipWriting, selectedProperties, odataUri, this.CurrentScope);
}

/// <summary>
Expand Down Expand Up @@ -1822,7 +1822,6 @@ await this.asynchronousJsonWriter.EndArrayScopeAsync()
protected override async Task StartDeletedResourceAsync(ODataDeletedResource resource)
{
Debug.Assert(resource != null, "resource != null");
Debug.Assert(!this.IsTopLevel, "Delta resource cannot be on top level.");
DeletedResourceScope resourceScope = this.CurrentDeletedResourceScope;
Debug.Assert(resourceScope != null, "Writing deleted entry and scope is not DeltaResourceScope");

Expand All @@ -1849,7 +1848,7 @@ await this.WriteDeletedEntryContentsAsync(resource)
{
// Writing a deleted resource within an entity set
DeltaResourceSetScope deltaResourceSetScope = this.ParentScope as DeltaResourceSetScope;
Debug.Assert(deltaResourceSetScope != null, "Writing child of delta set and parent scope is not DeltaResourceSetScope");
Debug.Assert(this.ParentScope.State == WriterState.Start || deltaResourceSetScope != null, "Writing child of delta set and parent scope is not DeltaResourceSetScope");

await this.asynchronousJsonWriter.StartObjectScopeAsync()
.ConfigureAwait(false);
Expand All @@ -1860,27 +1859,27 @@ await this.asynchronousJsonWriter.StartObjectScopeAsync()
await this.jsonLightResourceSerializer.WriteDeltaContextUriAsync(
this.CurrentDeletedResourceScope.GetOrCreateTypeContext(this.writingResponse),
ODataDeltaKind.DeletedEntry,
deltaResourceSetScope.ContextUriInfo).ConfigureAwait(false);
deltaResourceSetScope?.ContextUriInfo).ConfigureAwait(false);
await this.WriteV4DeletedEntryContentsAsync(resource)
.ConfigureAwait(false);
}
else
{
// Only write ContextUrl for V4.01 deleted resource if it is in a top level delta
// resource set and comes from a different entity set
string expectedNavigationSource = deltaResourceSetScope.NavigationSource?.Name;
string expectedNavigationSource = deltaResourceSetScope?.NavigationSource?.Name;
string currentNavigationSource = resource.SerializationInfo?.NavigationSourceName ?? resourceScope.NavigationSource?.Name;

if (String.IsNullOrEmpty(currentNavigationSource) || currentNavigationSource != expectedNavigationSource)
{
Debug.Assert(this.ScopeLevel == 3, "Writing a nested deleted resource of the wrong type should already have been caught.");
Debug.Assert(this.ScopeLevel <= 3, "Writing a nested deleted resource of the wrong type should already have been caught.");

// We are writing a deleted resource in a top level delta resource set
// from a different entity set, so include the context Url
await this.jsonLightResourceSerializer.WriteDeltaContextUriAsync(
this.CurrentDeletedResourceScope.GetOrCreateTypeContext(this.writingResponse),
ODataDeltaKind.DeletedEntry,
deltaResourceSetScope.ContextUriInfo).ConfigureAwait(false);
deltaResourceSetScope?.ContextUriInfo).ConfigureAwait(false);
}

await this.WriteDeletedEntryContentsAsync(resource)
Expand Down Expand Up @@ -3579,8 +3578,9 @@ private sealed class JsonLightNestedResourceInfoScope : NestedResourceInfoScope
/// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
/// <param name="selectedProperties">The selected properties of this scope.</param>
/// <param name="odataUri">The ODataUri info of this scope.</param>
internal JsonLightNestedResourceInfoScope(WriterState writerState, ODataNestedResourceInfo navLink, IEdmNavigationSource navigationSource, IEdmType itemType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
: base(writerState, navLink, navigationSource, itemType, skipWriting, selectedProperties, odataUri)
/// <param name="parentScope">The scope of the parent.</param>
internal JsonLightNestedResourceInfoScope(WriterState writerState, ODataNestedResourceInfo navLink, IEdmNavigationSource navigationSource, IEdmType itemType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri, Scope parentScope)
: base(writerState, navLink, navigationSource, itemType, skipWriting, selectedProperties, odataUri, parentScope)
{
}

Expand Down Expand Up @@ -3623,7 +3623,7 @@ internal bool ResourceSetWritten
/// <returns>The cloned nested resource info scope with the specified writer state.</returns>
internal override NestedResourceInfoScope Clone(WriterState newWriterState)
{
return new JsonLightNestedResourceInfoScope(newWriterState, (ODataNestedResourceInfo)this.Item, this.NavigationSource, this.ItemType, this.SkipWriting, this.SelectedProperties, this.ODataUri)
return new JsonLightNestedResourceInfoScope(newWriterState, (ODataNestedResourceInfo)this.Item, this.NavigationSource, this.ItemType, this.SkipWriting, this.SelectedProperties, this.ODataUri, this.parentScope)
{
EntityReferenceLinkWritten = this.entityReferenceLinkWritten,
ResourceSetWritten = this.resourceSetWritten,
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.OData.Core/Microsoft.OData.Core.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ODataWriterCore_DeltaResourceWithoutIdOrKeyProperties=No Id or key properties we
ODataWriterCore_QueryCountInRequest=The ODataResourceSet.Count must be null for request payloads. Query counts are only supported in responses.
ODataWriterCore_QueryNextLinkInRequest=The NextPageLink must be null for request payloads. Next page links are only supported in responses.
ODataWriterCore_QueryDeltaLinkInRequest=The DeltaLink must be null for request payloads. Delta links are only supported in responses.
ODataWriterCore_CannotWriteDeltaWithResourceSetWriter=Cannot write a deleted resource, link, deleted link, or nested delta resource set to a non-delta payload. Please use a delta resource set writer, or a request resource writer.
ODataWriterCore_CannotWriteDeltaWithResourceSetWriter=Cannot write a deleted resource, link, deleted link, or nested delta resource set within a resource set; they must be written within a delta resource set.
ODataWriterCore_NestedContentNotAllowedIn40DeletedEntry=Nested content is not allowed in an OData 4.0 deleted entry. For content in deleted entries, please specify OData 4.01 or greater.
ODataWriterCore_CannotWriteTopLevelResourceSetWithResourceWriter=Cannot write a top-level resource set with a writer that was created to write a top-level resource.
ODataWriterCore_CannotWriteTopLevelResourceWithResourceSetWriter=Cannot write a top-level resource with a writer that was created to write a top-level resource set.
Expand Down