Index: Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/Ringtoets.StabilityPointStructures.Service.csproj =================================================================== diff -u -rfcad48d7beb394e1ac15cfe4289a7381e05aa883 -re6a49aa13427aabc6faec5da41362b72adb2e806 --- Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/Ringtoets.StabilityPointStructures.Service.csproj (.../Ringtoets.StabilityPointStructures.Service.csproj) (revision fcad48d7beb394e1ac15cfe4289a7381e05aa883) +++ Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/Ringtoets.StabilityPointStructures.Service.csproj (.../Ringtoets.StabilityPointStructures.Service.csproj) (revision e6a49aa13427aabc6faec5da41362b72adb2e806) @@ -69,6 +69,11 @@ Ringtoets.StabilityPointStructures.Forms False + + {c8832e89-8543-4f2b-9952-8d6c03118392} + Ringtoets.StabilityPointStructures.Util + False + Index: Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/StabilityPointStructuresDataSynchronizationService.cs =================================================================== diff -u -rac8798cf0a66cf04df1294d4fd08e0b1915a5b91 -re6a49aa13427aabc6faec5da41362b72adb2e806 --- Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/StabilityPointStructuresDataSynchronizationService.cs (.../StabilityPointStructuresDataSynchronizationService.cs) (revision ac8798cf0a66cf04df1294d4fd08e0b1915a5b91) +++ Ringtoets/StabilityPointStructures/src/Ringtoets.StabilityPointStructures.Service/StabilityPointStructuresDataSynchronizationService.cs (.../StabilityPointStructuresDataSynchronizationService.cs) (revision e6a49aa13427aabc6faec5da41362b72adb2e806) @@ -23,12 +23,13 @@ using System.Collections.Generic; using System.Linq; using Core.Common.Base; +using Ringtoets.Common.Data; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.Hydraulics; using Ringtoets.Common.Data.Structures; using Ringtoets.Common.Service; -using Ringtoets.Common.Util; using Ringtoets.StabilityPointStructures.Data; +using Ringtoets.StabilityPointStructures.Util; namespace Ringtoets.StabilityPointStructures.Service { @@ -38,6 +39,73 @@ public static class StabilityPointStructuresDataSynchronizationService { /// + /// Clears all structures, unassigns them from the calculations in the + /// and clears all data that depends on it, either directly or indirectly. + /// + /// The to + /// clear the structures from. + /// All objects that are affected by this operation. + /// Thrown when any parameter is null. + public static IEnumerable RemoveAllStructures(StabilityPointStructuresFailureMechanism failureMechanism) + { + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + + IEnumerable> calculations = + failureMechanism.Calculations.Cast>(); + StructuresCalculation[] calculationWithRemovedStructure = calculations + .Where(c => c.InputParameters.Structure != null) + .ToArray(); + + List changedObservables = ClearStructureDependentData(failureMechanism, + calculationWithRemovedStructure); + + StructureCollection structures = failureMechanism.StabilityPointStructures; + structures.Clear(); + changedObservables.Add(structures); + + return changedObservables; + } + + /// + /// Removes the given stability point structure and all dependent data, either + /// directly or indirectly, from the failure mechanism. + /// + /// The structure to be removed. + /// The failure mechanism containing . + /// All objects affected by the removal. + /// Thrown when any parameter is null. + public static IEnumerable RemoveStructure(StabilityPointStructure structure, StabilityPointStructuresFailureMechanism failureMechanism) + { + if (structure == null) + { + throw new ArgumentNullException(nameof(structure)); + } + + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + + IEnumerable> stabilityPointStructureCalculations = + failureMechanism.Calculations + .Cast>(); + IEnumerable> calculationWithRemovedStabilityPointStructure = + stabilityPointStructureCalculations + .Where(c => ReferenceEquals(c.InputParameters.Structure, structure)) + .ToArray(); + + List changedObservables = ClearStructureDependentData(failureMechanism, calculationWithRemovedStabilityPointStructure); + + failureMechanism.StabilityPointStructures.Remove(structure); + changedObservables.Add(failureMechanism.StabilityPointStructures); + + return changedObservables; + } + + /// /// Clears the output for all calculations in the . /// /// The @@ -125,47 +193,6 @@ return new ClearResults(changedObjects, removedObjects); } - /// - /// Removes the given stability point structure and all dependent data, either - /// directly or indirectly, from the failure mechanism. - /// - /// The failure mechanism containing . - /// The structure to be removed. - /// All objects affected by the removal. - public static IEnumerable RemoveStructure(StabilityPointStructuresFailureMechanism failureMechanism, - StabilityPointStructure structure) - { - var changedObservables = new HashSet(); - StructuresCalculation[] stabilityPointStructureCalculations = failureMechanism.Calculations - .Cast>() - .ToArray(); - StructuresCalculation[] calculationWithRemovedStabilityPointStructure = stabilityPointStructureCalculations - .Where(c => ReferenceEquals(c.InputParameters.Structure, structure)) - .ToArray(); - foreach (StructuresCalculation calculation in calculationWithRemovedStabilityPointStructure) - { - foreach (IObservable calculationWithRemovedOutput in RingtoetsCommonDataSynchronizationService.ClearCalculationOutput(calculation)) - { - changedObservables.Add(calculationWithRemovedOutput); - } - - calculation.InputParameters.Structure = null; - changedObservables.Add(calculation.InputParameters); - } - - IEnumerable> affectedSectionResults = - StructuresHelper.UpdateCalculationToSectionResultAssignments(failureMechanism.SectionResults, stabilityPointStructureCalculations); - foreach (StructuresFailureMechanismSectionResult result in affectedSectionResults) - { - changedObservables.Add(result); - } - - failureMechanism.StabilityPointStructures.Remove(structure); - changedObservables.Add(failureMechanism.StabilityPointStructures); - - return changedObservables; - } - private static IEnumerable ClearHydraulicBoundaryLocation(StabilityPointStructuresInput input) { if (input.HydraulicBoundaryLocation != null) @@ -176,7 +203,27 @@ input }; } + return Enumerable.Empty(); } + + private static List ClearStructureDependentData(StabilityPointStructuresFailureMechanism failureMechanism, + IEnumerable> calculationWithRemovedStructure) + { + var changedObservables = new List(); + foreach (StructuresCalculation calculation in calculationWithRemovedStructure) + { + changedObservables.AddRange(RingtoetsCommonDataSynchronizationService.ClearCalculationOutput(calculation)); + + calculation.InputParameters.ClearStructure(); + changedObservables.Add(calculation.InputParameters); + } + + IEnumerable affectedSectionResults = + StabilityPointStructuresHelper.UpdateCalculationToSectionResultAssignments(failureMechanism); + + changedObservables.AddRange(affectedSectionResults); + return changedObservables; + } } } \ No newline at end of file Index: Ringtoets/StabilityPointStructures/test/Ringtoets.StabilityPointStructures.Service.Test/StabilityPointStructuresDataSynchronizationServiceTest.cs =================================================================== diff -u -rac8798cf0a66cf04df1294d4fd08e0b1915a5b91 -re6a49aa13427aabc6faec5da41362b72adb2e806 --- Ringtoets/StabilityPointStructures/test/Ringtoets.StabilityPointStructures.Service.Test/StabilityPointStructuresDataSynchronizationServiceTest.cs (.../StabilityPointStructuresDataSynchronizationServiceTest.cs) (revision ac8798cf0a66cf04df1294d4fd08e0b1915a5b91) +++ Ringtoets/StabilityPointStructures/test/Ringtoets.StabilityPointStructures.Service.Test/StabilityPointStructuresDataSynchronizationServiceTest.cs (.../StabilityPointStructuresDataSynchronizationServiceTest.cs) (revision e6a49aa13427aabc6faec5da41362b72adb2e806) @@ -39,6 +39,116 @@ public class StabilityPointStructuresDataSynchronizationServiceTest { [Test] + public void RemoveAllStructures_FailureMechanismNull_ThrowsArgumentNullException() + { + // Call + TestDelegate call = () => StabilityPointStructuresDataSynchronizationService.RemoveAllStructures(null); + + // Assert + string paramName = Assert.Throws(call).ParamName; + Assert.AreEqual("failureMechanism", paramName); + } + + [Test] + public void RemoveAllStructures_FullyConfiguredFailureMechanism_RemoveAllStructuresAndClearDependentData() + { + // Setup + var failureMechanism = new StabilityPointStructuresFailureMechanism(); + + var locationStructureA = new Point2D(0, 0); + var structureA = new TestStabilityPointStructure(locationStructureA, "A"); + + var locationStructureB = new Point2D(2, 2); + var structureB = new TestStabilityPointStructure(locationStructureB, "B"); + + failureMechanism.StabilityPointStructures.AddRange(new[] + { + structureA, + structureB + }, "path/to/structures"); + + var calculationWithOutput = new StructuresCalculation + { + Output = new TestStructuresOutput() + }; + var calculationWithStructureA = new StructuresCalculation + { + InputParameters = + { + Structure = structureA + } + }; + var calculationWithStructureBAndOutput = new StructuresCalculation + { + InputParameters = + { + Structure = structureB + }, + Output = new TestStructuresOutput() + }; + var calculationWithStructureAAndOutput = new StructuresCalculation + { + InputParameters = + { + Structure = structureA + }, + Output = new TestStructuresOutput() + }; + failureMechanism.CalculationsGroup.Children.AddRange(new[] + { + calculationWithOutput, + calculationWithStructureA, + calculationWithStructureBAndOutput, + calculationWithStructureAAndOutput + }); + + failureMechanism.AddSection(FailureMechanismSectionTestFactory.CreateFailureMechanismSection(new[] + { + locationStructureA, + new Point2D(1, 1) + })); + StabilityPointStructuresFailureMechanismSectionResult sectionWithCalculationAtStructureA = failureMechanism.SectionResults2.ElementAt(0); + sectionWithCalculationAtStructureA.Calculation = calculationWithStructureA; + + failureMechanism.AddSection(FailureMechanismSectionTestFactory.CreateFailureMechanismSection(new[] + { + new Point2D(1, 1), + locationStructureB + })); + StabilityPointStructuresFailureMechanismSectionResult sectionWithCalculationAtStructureB = failureMechanism.SectionResults2.ElementAt(1); + sectionWithCalculationAtStructureB.Calculation = calculationWithStructureBAndOutput; + + // Call + IEnumerable affectedObjects = StabilityPointStructuresDataSynchronizationService.RemoveAllStructures(failureMechanism); + + // Assert + // Note: To make sure the clear is performed regardless of what is done with + // the return result, no ToArray() should be called before these assertions: + CollectionAssert.DoesNotContain(failureMechanism.StabilityPointStructures, structureA); + Assert.IsNull(calculationWithStructureA.InputParameters.Structure); + Assert.IsNull(calculationWithStructureAAndOutput.InputParameters.Structure); + Assert.IsNull(calculationWithStructureBAndOutput.InputParameters.Structure); + Assert.IsNull(calculationWithStructureAAndOutput.Output); + Assert.IsNull(calculationWithStructureBAndOutput.Output); + Assert.IsNull(sectionWithCalculationAtStructureA.Calculation); + Assert.IsNull(sectionWithCalculationAtStructureB.Calculation); + Assert.IsNotNull(calculationWithOutput.Output); + + IObservable[] expectedAffectedObjects = + { + calculationWithStructureA.InputParameters, + calculationWithStructureAAndOutput, + calculationWithStructureAAndOutput.InputParameters, + calculationWithStructureBAndOutput, + calculationWithStructureBAndOutput.InputParameters, + sectionWithCalculationAtStructureA, + sectionWithCalculationAtStructureB, + failureMechanism.StabilityPointStructures + }; + CollectionAssert.AreEquivalent(expectedAffectedObjects, affectedObjects); + } + + [Test] public void ClearAllCalculationOutput_FailureMechanismNull_ThrowsArgumentNullException() { // Call @@ -156,18 +266,40 @@ } [Test] - public void RemoveStabilityPointStructure_FullyConfiguredFailureMechanism_RemovesStructureAndClearsDependentData() + public void RemoveStructure_StructureNull_ThrowsArgumentNullException() { + // Call + TestDelegate call = () => StabilityPointStructuresDataSynchronizationService.RemoveStructure(null, new StabilityPointStructuresFailureMechanism()); + + // Assert + var exception = Assert.Throws(call); + Assert.AreEqual("structure", exception.ParamName); + } + + [Test] + public void RemoveStructure_FailureMechanismNull_ThrowsArgumentNullException() + { + // Call + TestDelegate call = () => StabilityPointStructuresDataSynchronizationService.RemoveStructure(new TestStabilityPointStructure(), null); + + // Assert + var exception = Assert.Throws(call); + Assert.AreEqual("failureMechanism", exception.ParamName); + } + + [Test] + public void RemoveStructure_FullyConfiguredFailureMechanism_RemovesStructureAndClearsDependentData() + { // Setup StabilityPointStructuresFailureMechanism failureMechanism = CreateFullyConfiguredFailureMechanism(); StabilityPointStructure structure = failureMechanism.StabilityPointStructures[0]; StructuresCalculation[] calculationsWithStructure = failureMechanism.Calculations .Cast>() .Where(c => ReferenceEquals(c.InputParameters.Structure, structure)) .ToArray(); - StructuresFailureMechanismSectionResult[] sectionResultsWithStructure = failureMechanism.SectionResults - .Where(sr => calculationsWithStructure.Contains(sr.Calculation)) - .ToArray(); + StabilityPointStructuresFailureMechanismSectionResult[] sectionResultsWithStructure = failureMechanism.SectionResults2 + .Where(sr => calculationsWithStructure.Contains(sr.Calculation)) + .ToArray(); StructuresCalculation[] calculationsWithOutput = calculationsWithStructure.Where(c => c.HasOutput) .ToArray(); @@ -182,7 +314,7 @@ CollectionAssert.IsNotEmpty(sectionResultsWithStructure); // Call - IEnumerable affectedObjects = StabilityPointStructuresDataSynchronizationService.RemoveStructure(failureMechanism, structure); + IEnumerable affectedObjects = StabilityPointStructuresDataSynchronizationService.RemoveStructure(structure, failureMechanism); // Assert // Note: To make sure the clear is performed regardless of what is done with @@ -198,7 +330,7 @@ Assert.IsFalse(calculation.HasOutput); } - foreach (StructuresFailureMechanismSectionResult sectionResult in sectionResultsWithStructure) + foreach (StabilityPointStructuresFailureMechanismSectionResult sectionResult in sectionResultsWithStructure) { Assert.IsNull(sectionResult.Calculation); } @@ -217,7 +349,7 @@ CollectionAssert.Contains(array, calculation); } - foreach (StructuresFailureMechanismSectionResult result in sectionResultsWithStructure) + foreach (StabilityPointStructuresFailureMechanismSectionResult result in sectionResultsWithStructure) { CollectionAssert.Contains(array, result); } @@ -297,10 +429,10 @@ failureMechanism.AddSection(section1); failureMechanism.AddSection(section2); - StructuresFailureMechanismSectionResult result1 = failureMechanism.SectionResults - .First(sr => ReferenceEquals(sr.Section, section1)); - StructuresFailureMechanismSectionResult result2 = failureMechanism.SectionResults - .First(sr => ReferenceEquals(sr.Section, section2)); + StabilityPointStructuresFailureMechanismSectionResult result1 = failureMechanism.SectionResults2 + .First(sr => ReferenceEquals(sr.Section, section1)); + StabilityPointStructuresFailureMechanismSectionResult result2 = failureMechanism.SectionResults2 + .First(sr => ReferenceEquals(sr.Section, section2)); result1.Calculation = calculation1; result2.Calculation = calculation2;