Index: Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil.Test/TestCalculationWithForeshoreProfileTest.cs =================================================================== diff -u -rb1acb656284ee0a7db2384e83d2b36f64fa57dc8 -r474b2334202ee2bfbe8df476845bd7e2fca01803 --- Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil.Test/TestCalculationWithForeshoreProfileTest.cs (.../TestCalculationWithForeshoreProfileTest.cs) (revision b1acb656284ee0a7db2384e83d2b36f64fa57dc8) +++ Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil.Test/TestCalculationWithForeshoreProfileTest.cs (.../TestCalculationWithForeshoreProfileTest.cs) (revision 474b2334202ee2bfbe8df476845bd7e2fca01803) @@ -19,6 +19,7 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using NUnit.Framework; namespace Ringtoets.Common.Data.TestUtil.Test @@ -40,6 +41,18 @@ } [Test] + public void CreateCalculationWithOutput_ForeshoreProfileNull_ThrowsArgumentNullException() + { + // Call + TestDelegate call = () => + TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(null); + + // Assert + var exception = Assert.Throws(call); + Assert.AreEqual("foreshoreProfile", exception.ParamName); + } + + [Test] public void CreateCalculationWithOutput_ReturnsExpectedValues() { // Setup @@ -76,7 +89,7 @@ { // Given var foreshoreProfile = new TestForeshoreProfile(); - var calculation = + TestCalculationWithForeshoreProfile calculation = TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(foreshoreProfile); // When @@ -91,7 +104,7 @@ { // Given var foreshoreProfile = new TestForeshoreProfile(); - var calculation = + TestCalculationWithForeshoreProfile calculation = TestCalculationWithForeshoreProfile.CreateCalculationWithoutOutput(foreshoreProfile); // When Index: Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil/TestCalculationWithForeshoreProfile.cs =================================================================== diff -u -rb1acb656284ee0a7db2384e83d2b36f64fa57dc8 -r474b2334202ee2bfbe8df476845bd7e2fca01803 --- Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil/TestCalculationWithForeshoreProfile.cs (.../TestCalculationWithForeshoreProfile.cs) (revision b1acb656284ee0a7db2384e83d2b36f64fa57dc8) +++ Ringtoets/Common/test/Ringtoets.Common.Data.TestUtil/TestCalculationWithForeshoreProfile.cs (.../TestCalculationWithForeshoreProfile.cs) (revision 474b2334202ee2bfbe8df476845bd7e2fca01803) @@ -54,8 +54,15 @@ /// The foreshore profile assigned to the calculation. /// A with a foreshore and /// calculation output. + /// Thrown when + /// is null. public static TestCalculationWithForeshoreProfile CreateCalculationWithOutput(ForeshoreProfile foreshoreProfile) { + if (foreshoreProfile == null) + { + throw new ArgumentNullException(nameof(foreshoreProfile)); + } + return new TestCalculationWithForeshoreProfile(true) { InputParameters = Index: Ringtoets/Integration/src/Ringtoets.Integration.Plugin/FileImporters/ForeshoreProfileUpdateDataStrategy.cs =================================================================== diff -u -r3327c16cf8fc44952976b5505944226edf78fe1c -r474b2334202ee2bfbe8df476845bd7e2fca01803 --- Ringtoets/Integration/src/Ringtoets.Integration.Plugin/FileImporters/ForeshoreProfileUpdateDataStrategy.cs (.../ForeshoreProfileUpdateDataStrategy.cs) (revision 3327c16cf8fc44952976b5505944226edf78fe1c) +++ Ringtoets/Integration/src/Ringtoets.Integration.Plugin/FileImporters/ForeshoreProfileUpdateDataStrategy.cs (.../ForeshoreProfileUpdateDataStrategy.cs) (revision 474b2334202ee2bfbe8df476845bd7e2fca01803) @@ -21,38 +21,83 @@ using System; using System.Collections.Generic; +using System.Linq; using Core.Common.Base; +using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.DikeProfiles; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.Common.Data.UpdateDataStrategies; using Ringtoets.Common.IO.FileImporters; +using Ringtoets.Common.Service; namespace Ringtoets.Integration.Plugin.FileImporters { + /// + /// An for + /// updating surface lines based on imported data. + /// public class ForeshoreProfileUpdateDataStrategy : UpdateDataStrategyBase, IForeshoreProfileUpdateDataStrategy { - public ForeshoreProfileUpdateDataStrategy(IFailureMechanism failureMechanism) : base(failureMechanism, new ForeshoreProfileEqualityComparer()) {} + /// + /// Creates a new instance of . + /// + /// The failure mechanism in which the + /// are updated. + /// Thrown when + /// is null. + public ForeshoreProfileUpdateDataStrategy(IFailureMechanism failureMechanism) + : base(failureMechanism, new ForeshoreProfileEqualityComparer()) {} + public IEnumerable UpdateForeshoreProfilesWithImportedData(ForeshoreProfileCollection targetDataCollection, + IEnumerable importedDataCollection, + string sourceFilePath) + { + return UpdateTargetCollectionData(targetDataCollection, importedDataCollection, sourceFilePath); + } protected override IEnumerable UpdateObjectAndDependentData(ForeshoreProfile objectToUpdate, ForeshoreProfile objectToUpdateFrom) { - objectToUpdate.CopyProperties(objectToUpdateFrom); - return new IObservable[] + var affectedObjects = new List(); + if (!objectToUpdate.Equals(objectToUpdateFrom)) { - objectToUpdate - }; + objectToUpdate.CopyProperties(objectToUpdateFrom); + affectedObjects.Add(objectToUpdate); + + IEnumerable> affectedCalculations = GetAffectedCalculationWithSurfaceLines(objectToUpdate); + + foreach (ICalculation calculation in affectedCalculations) + { + affectedObjects.Add(calculation.InputParameters); + affectedObjects.AddRange(RingtoetsCommonDataSynchronizationService.ClearCalculationOutput(calculation)); + } + } + + return affectedObjects; } protected override IEnumerable RemoveObjectAndDependentData(ForeshoreProfile removedObject) { - // TODO - return new IObservable[0]; + IEnumerable> affectedCalculations = GetAffectedCalculationWithSurfaceLines(removedObject); + + var affectedObjects = new List(); + foreach (ICalculation calculation in affectedCalculations) + { + ((IHasForeshoreProfile) calculation.InputParameters).ForeshoreProfile = null; + affectedObjects.Add(calculation.InputParameters); + affectedObjects.AddRange(RingtoetsCommonDataSynchronizationService.ClearCalculationOutput(calculation)); + } + + return affectedObjects; } - public IEnumerable UpdateForeshoreProfilesWithImportedData(ForeshoreProfileCollection targetDataCollection, IEnumerable importedDataCollection, string sourceFilePath) + private IEnumerable> GetAffectedCalculationWithSurfaceLines(ForeshoreProfile foreshoreProfile) { - return UpdateTargetCollectionData(targetDataCollection, importedDataCollection, sourceFilePath); + IEnumerable> calculations = FailureMechanism.Calculations.Cast>(); + IEnumerable> affectedCalculations = + calculations.Where(calc => ReferenceEquals( + ((IHasForeshoreProfile) calc.InputParameters).ForeshoreProfile, foreshoreProfile)); + return affectedCalculations; } /// Index: Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/FileImporters/ForeshoreProfileUpdateDataStrategyTest.cs =================================================================== diff -u -r3327c16cf8fc44952976b5505944226edf78fe1c -r474b2334202ee2bfbe8df476845bd7e2fca01803 --- Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/FileImporters/ForeshoreProfileUpdateDataStrategyTest.cs (.../ForeshoreProfileUpdateDataStrategyTest.cs) (revision 3327c16cf8fc44952976b5505944226edf78fe1c) +++ Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/FileImporters/ForeshoreProfileUpdateDataStrategyTest.cs (.../ForeshoreProfileUpdateDataStrategyTest.cs) (revision 474b2334202ee2bfbe8df476845bd7e2fca01803) @@ -58,7 +58,7 @@ { // Setup var profileToBeUpdated = new TestForeshoreProfile("Name", "Profile ID"); - var profileToUpdateFrom = DeepCloneAndModify(profileToBeUpdated); + ForeshoreProfile profileToUpdateFrom = DeepCloneAndModify(profileToBeUpdated); var targetCollection = new ForeshoreProfileCollection(); targetCollection.AddRange(new[] @@ -120,7 +120,7 @@ // Assert var exception = Assert.Throws(call); - string expectedMessage = $"Voorlandprofielen moeten een unieke id hebben. Gevonden dubbele elementen: {duplicateId}."; + const string expectedMessage = "Geïmporteerde data moet unieke elementen bevatten."; Assert.AreEqual(expectedMessage, exception.Message); CollectionAssert.IsEmpty(foreshoreProfiles); @@ -206,10 +206,10 @@ // Assert var exception = Assert.Throws(call); - string expectedMessage = $"Voorlandprofielen moeten een unieke id hebben. Gevonden dubbele elementen: {duplicateId}."; + const string expectedMessage = "Geïmporteerde data moet unieke elementen bevatten."; Assert.AreEqual(expectedMessage, exception.Message); - CollectionAssert.IsEmpty(foreshoreProfiles); + CollectionAssert.AreEqual(originalForeshoreProfiles, foreshoreProfiles); } [Test] @@ -263,7 +263,7 @@ targetForeshoreProfile }, sourceFilePath); - var readForeshoreProfile = DeepCloneAndModify(targetForeshoreProfile); + ForeshoreProfile readForeshoreProfile = DeepCloneAndModify(targetForeshoreProfile); var importedForeshoreProfiles = new[] { readForeshoreProfile @@ -303,7 +303,7 @@ foreshoreProfileToBeRemoved }, sourceFilePath); - var foreshoreProfileToUpdateFrom = DeepCloneAndModify(foreshoreProfileToBeUpdated); + ForeshoreProfile foreshoreProfileToUpdateFrom = DeepCloneAndModify(foreshoreProfileToBeUpdated); var foreshoreProfileToBeAdded = new TestForeshoreProfile(commonName, "Added ID"); var importedForeshoreProfiles = new[] { @@ -339,6 +339,157 @@ }, affectedObjects); } + [Test] + public void UpdateForeshoreProfilesWithImportedData_CalculationWithOutputAssignedToRemovedProfile_UpdatesCalculation() + { + // Setup + var profileToBeRemoved = new TestForeshoreProfile("Name", "Removed ID"); + TestCalculationWithForeshoreProfile calculation = + TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(profileToBeRemoved); + var foreshoreProfiles = new ForeshoreProfileCollection(); + foreshoreProfiles.AddRange(new[] + { + profileToBeRemoved + }, sourceFilePath); + + var failureMechanism = new TestFailureMechanism(new[] + { + calculation + }); + + var strategy = new ForeshoreProfileUpdateDataStrategy(failureMechanism); + + // Call + IEnumerable affectedObjects = + strategy.UpdateForeshoreProfilesWithImportedData(foreshoreProfiles, + Enumerable.Empty(), + sourceFilePath); + + // Assert + Assert.IsFalse(calculation.HasOutput); + Assert.IsNull(calculation.InputParameters.ForeshoreProfile); + + CollectionAssert.IsEmpty(foreshoreProfiles); + CollectionAssert.AreEquivalent(new IObservable[] + { + calculation, + calculation.InputParameters, + foreshoreProfiles + }, affectedObjects); + } + + [Test] + public void UpdateForeshoreProfilesWithImportedData_MultipleCalculationsWithOutputAndProfile_UpdatesCalculationWithUpdatedProfile() + { + // Setup + var affectedProfile = new TestForeshoreProfile("Name", "Updated ID"); + TestCalculationWithForeshoreProfile affectedCalculation = + TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(affectedProfile); + ForeshoreProfile profileToUpdateFrom = DeepCloneAndModify(affectedProfile); + + const string unaffectedProfileId = "Unaffected ID"; + const string unaffectedProfileName = "Name"; + var unaffectedProfile = new TestForeshoreProfile(unaffectedProfileName, unaffectedProfileId); + TestCalculationWithForeshoreProfile unaffectedCalculation = + TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(unaffectedProfile); + + var foreshoreProfiles = new ForeshoreProfileCollection(); + var originalForeshoreProfiles = new[] + { + affectedProfile, + unaffectedProfile + }; + foreshoreProfiles.AddRange(originalForeshoreProfiles, sourceFilePath); + + var failureMechanism = new TestFailureMechanism(new[] + { + affectedCalculation, + unaffectedCalculation + }); + + var strategy = new ForeshoreProfileUpdateDataStrategy(failureMechanism); + + // Call + IEnumerable affectedObjects = + strategy.UpdateForeshoreProfilesWithImportedData(foreshoreProfiles, + new[] + { + new TestForeshoreProfile(unaffectedProfileName, + unaffectedProfileId), + profileToUpdateFrom + }, + sourceFilePath); + + // Assert + Assert.IsTrue(unaffectedCalculation.HasOutput); + Assert.AreSame(unaffectedProfile, + unaffectedCalculation.InputParameters.ForeshoreProfile); + + Assert.IsFalse(affectedCalculation.HasOutput); + Assert.AreSame(affectedProfile, affectedCalculation.InputParameters.ForeshoreProfile); + + CollectionAssert.AreEquivalent(originalForeshoreProfiles, foreshoreProfiles); + + CollectionAssert.AreEquivalent(new IObservable[] + { + affectedCalculation, + affectedCalculation.InputParameters, + affectedProfile, + foreshoreProfiles + }, affectedObjects); + } + + [Test] + public void UpdateForeshoreProfilesWithImportedData_MultipleCalculationsWithSameReference_OnlyReturnsDistinctCalculations() + { + // Setup + var affectedProfile = new TestForeshoreProfile("Name", "Updated ID"); + TestCalculationWithForeshoreProfile affectedCalculation = + TestCalculationWithForeshoreProfile.CreateCalculationWithOutput(affectedProfile); + ForeshoreProfile profileToUpdateFrom = DeepCloneAndModify(affectedProfile); + + TestCalculationWithForeshoreProfile calculationSameReference = affectedCalculation; + + var foreshoreProfiles = new ForeshoreProfileCollection(); + var originalForeshoreProfiles = new[] + { + affectedProfile, + }; + foreshoreProfiles.AddRange(originalForeshoreProfiles, sourceFilePath); + + var failureMechanism = new TestFailureMechanism(new[] + { + affectedCalculation, + calculationSameReference + }); + + var strategy = new ForeshoreProfileUpdateDataStrategy(failureMechanism); + + // Call + IEnumerable affectedObjects = + strategy.UpdateForeshoreProfilesWithImportedData(foreshoreProfiles, + new[] + { + profileToUpdateFrom + }, + sourceFilePath); + + // Assert + CollectionAssert.AreEquivalent(new IObservable[] + { + affectedCalculation, + affectedCalculation.InputParameters, + affectedProfile, + foreshoreProfiles + }, affectedObjects); + } + + /// + /// Makes a deep clone of the foreshore profile and modifies all the properties, + /// except the . + /// + /// The foreshore profile to deep clone. + /// A deep clone of the . private static ForeshoreProfile DeepCloneAndModify(ForeshoreProfile foreshoreProfile) { var random = new Random(21);