private async Task <IReadOnlyCollection <ChangeItem> > ApplySetAsync([NotNull] IEntry entry, [NotNull] Dictionary <XName, IUntypedReadableProperty> properties, [NotNull] propset set, bool previouslyFailed, CancellationToken cancellationToken) { var result = new List <ChangeItem>(); if (set.prop?.Any == null) { return(result); } var language = set.prop.Language; var failed = previouslyFailed; foreach (var element in set.prop.Any) { // Add a parent elements xml:lang to the element var elementLanguage = element.Attribute(XNamespace.Xml + "lang")?.Value; if (string.IsNullOrEmpty(elementLanguage) && !string.IsNullOrEmpty(language)) { element.SetAttributeValue(XNamespace.Xml + "lang", language); } if (failed) { result.Add(ChangeItem.FailedDependency(element.Name)); continue; } var property = FindProperty(properties, element.Name); if (property != null) { ChangeItem changeItem; try { var writeableProperty = property as IUntypedWriteableProperty; if (writeableProperty != null) { if (entry.FileSystem.PropertyStore == null && writeableProperty is IDeadProperty) { changeItem = ChangeItem.ReadOnly(property, element, "Cannot modify dead without property store"); } else { var oldValue = await writeableProperty .GetXmlValueAsync(cancellationToken) .ConfigureAwait(false); await writeableProperty .SetXmlValueAsync(element, cancellationToken) .ConfigureAwait(false); changeItem = ChangeItem.Modified(property, element, oldValue); } } else { changeItem = ChangeItem.ReadOnly(property, element, "Cannot modify protected property"); } } catch (Exception ex) { changeItem = ChangeItem.Failed(property, ex.Message); } failed = !changeItem.IsSuccess; result.Add(changeItem); } else { if (entry.FileSystem.PropertyStore == null) { result.Add(ChangeItem.InsufficientStorage(element, "Cannot add dead property without property store")); failed = true; } else { var newProperty = new DeadProperty(entry.FileSystem.PropertyStore, entry, element); properties.Add(newProperty.Name, newProperty); await newProperty.SetXmlValueAsync(element, cancellationToken) .ConfigureAwait(false); result.Add(ChangeItem.Added(newProperty, element)); } } } return(result); }
private async Task <IReadOnlyCollection <ChangeItem> > ApplyRemoveAsync([NotNull] IEntry entry, [NotNull] IReadOnlyDictionary <XName, IUntypedReadableProperty> properties, [NotNull] propremove remove, bool previouslyFailed, CancellationToken cancellationToken) { var result = new List <ChangeItem>(); if (remove.prop?.Any == null) { return(result); } var language = remove.prop.Language; var failed = previouslyFailed; foreach (var element in remove.prop.Any) { // Add a parent elements xml:lang to the element var elementLanguage = element.Attribute(XNamespace.Xml + "lang")?.Value; if (string.IsNullOrEmpty(elementLanguage) && !string.IsNullOrEmpty(language)) { element.SetAttributeValue(XNamespace.Xml + "lang", language); } var propertyKey = element.Name; if (failed) { result.Add(ChangeItem.FailedDependency(propertyKey)); continue; } var property = FindProperty(properties, propertyKey); if (property != null) { if (!(property is IUntypedWriteableProperty)) { result.Add(ChangeItem.ReadOnly(property, element, "Cannot remove protected property")); } else if (entry.FileSystem.PropertyStore == null) { if (property is IDeadProperty) { result.Add(ChangeItem.ReadOnly(property, element, "Cannot remove dead without property store")); } else { result.Add(ChangeItem.ReadOnly(property, element, "Cannot remove live property")); } } else if (property is ILiveProperty) { result.Add(ChangeItem.Failed(property, "Cannot remove live property")); } else { try { var oldValue = await property.GetXmlValueAsync(cancellationToken).ConfigureAwait(false); var success = await entry.FileSystem.PropertyStore.RemoveAsync(entry, propertyKey, cancellationToken).ConfigureAwait(false); // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (!success) { result.Add(ChangeItem.Failed(property, "Couldn't remove property from property store (concurrent access?)")); } else { result.Add(ChangeItem.Removed(property, oldValue)); } } catch (Exception ex) { result.Add(ChangeItem.Failed(property, ex.Message)); failed = true; } } } else { result.Add(ChangeItem.Removed(propertyKey)); } } return(result); }