private static IEnumerable <ActionResult> Flatten([NotNull] CollectionActionResult collectionResult) { yield return(collectionResult); if (collectionResult.DocumentActionResults != null) { foreach (var result in collectionResult.DocumentActionResults) { yield return(result); } } if (collectionResult.CollectionActionResults != null) { foreach (var result in collectionResult.CollectionActionResults) { yield return(result); } } }
private async Task <CollectionActionResult> ExecuteAsync( Uri sourceUrl, ICollectionNode sourceNode, TCollection target, IReadOnlyCollection <IUntypedWriteableProperty> properties, CancellationToken cancellationToken) { if (_logger.IsEnabled(LogLevel.Trace)) { _logger.LogTrace($"Perform operation on collection {sourceUrl} with existing target {target.DestinationUrl}."); } var documentActionResults = ImmutableList <ActionResult> .Empty; var collectionActionResults = ImmutableList <CollectionActionResult> .Empty; var subNodeProperties = new Dictionary <string, IReadOnlyCollection <IUntypedWriteableProperty> >(); foreach (var childNode in sourceNode.Nodes) { var subProperties = await GetWriteableProperties(childNode.Collection, cancellationToken).ConfigureAwait(false); subNodeProperties.Add(childNode.Name, subProperties); } foreach (var document in sourceNode.Documents) { var docUrl = sourceUrl.Append(document); if (target.Created) { // Collection was created by us - we just assume that the document doesn't exist var missingTarget = target.NewMissing(document.Name); var docResult = await ExecuteAsync(docUrl, document, missingTarget, cancellationToken).ConfigureAwait(false); documentActionResults = documentActionResults.Add(docResult); } else { var foundTarget = await target.GetAsync(document.Name, cancellationToken).ConfigureAwait(false); var docTarget = foundTarget as TDocument; if (docTarget != null) { // We found a document: Business as usual when we're allowed to overwrite it var docResult = await ExecuteAsync(docUrl, document, docTarget, cancellationToken).ConfigureAwait(false); documentActionResults = documentActionResults.Add(docResult); } else { var collTarget = foundTarget as TCollection; if (collTarget != null) { // We found a collection instead of a document _logger.LogDebug($"{target.DestinationUrl}: Found a collection instead of a document"); var docResult = new ActionResult(ActionStatus.OverwriteFailed, foundTarget); documentActionResults = documentActionResults.Add(docResult); } else { // We didn't find anything: Business as usual var missingTarget = (TMissing)foundTarget; var docResult = await ExecuteAsync(docUrl, document, missingTarget, cancellationToken).ConfigureAwait(false); documentActionResults = documentActionResults.Add(docResult); } } } } foreach (var childNode in sourceNode.Nodes) { var childProperties = subNodeProperties[childNode.Name]; var collection = childNode.Collection; var docUrl = sourceUrl.Append(childNode.Collection); if (target.Created) { // Collection was created by us - we just assume that the sub collection doesn't exist var missingTarget = target.NewMissing(childNode.Name); var newColl = await missingTarget.CreateCollectionAsync(cancellationToken).ConfigureAwait(false); var collResult = await ExecuteAsync(docUrl, childNode, newColl, childProperties, cancellationToken).ConfigureAwait(false); collectionActionResults = collectionActionResults.Add(collResult); } else { // Test if the target node exists var foundTarget = await target.GetAsync(collection.Name, cancellationToken).ConfigureAwait(false); var docTarget = foundTarget as TDocument; if (docTarget != null) { // We found a document instead of a collection _logger.LogDebug($"{target.DestinationUrl}: Found a document instead of a collection"); var collResult = new CollectionActionResult(ActionStatus.OverwriteFailed, foundTarget); collectionActionResults = collectionActionResults.Add(collResult); } else { var collTarget = foundTarget as TCollection; if (collTarget != null) { // We found a collection: Business as usual var collResult = await ExecuteAsync(docUrl, childNode, collTarget, childProperties, cancellationToken).ConfigureAwait(false); collectionActionResults = collectionActionResults.Add(collResult); } else { // We didn't find anything: Business as usual var missingTarget = (TMissing)foundTarget; var newColl = await missingTarget.CreateCollectionAsync(cancellationToken).ConfigureAwait(false); var collResult = await ExecuteAsync(docUrl, childNode, newColl, childProperties, cancellationToken).ConfigureAwait(false); collectionActionResults = collectionActionResults.Add(collResult); } } } } try { if (_logger.IsEnabled(LogLevel.Trace)) { _logger.LogTrace($"Set properties on collection {target.DestinationUrl}."); } var failedPropertyNames = await target.SetPropertiesAsync(properties, cancellationToken).ConfigureAwait(false); if (failedPropertyNames.Count != 0) { _logger.LogDebug($"{target.DestinationUrl}: Failed setting properties {string.Join(", ", failedPropertyNames.Select(x => x.ToString()))}"); return(new CollectionActionResult(ActionStatus.PropSetFailed, target) { FailedProperties = failedPropertyNames, CollectionActionResults = collectionActionResults, DocumentActionResults = documentActionResults, }); } await _handler.ExecuteAsync(sourceNode.Collection, target, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.LogDebug($"{sourceNode.Collection.Path}: Cleanup failed with exception {ex.Message}"); return(new CollectionActionResult(ActionStatus.CleanupFailed, target) { Exception = ex, CollectionActionResults = collectionActionResults, DocumentActionResults = documentActionResults, }); } return(new CollectionActionResult(ActionStatus.Created, target) { CollectionActionResults = collectionActionResults, DocumentActionResults = documentActionResults, }); }