Index: Ringtoets/Piping/src/Ringtoets.Piping.Data/Ringtoets.Piping.Data.csproj =================================================================== diff -u -r6aaa17dbb25d6299115d68b221312aa1482d97a9 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Data/Ringtoets.Piping.Data.csproj (.../Ringtoets.Piping.Data.csproj) (revision 6aaa17dbb25d6299115d68b221312aa1482d97a9) +++ Ringtoets/Piping/src/Ringtoets.Piping.Data/Ringtoets.Piping.Data.csproj (.../Ringtoets.Piping.Data.csproj) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -67,6 +67,7 @@ + Index: Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModel.cs =================================================================== diff -u -r673bf2f4f4de6006444aae3a10183f9442eb0f23 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModel.cs (.../StochasticSoilModel.cs) (revision 673bf2f4f4de6006444aae3a10183f9442eb0f23) +++ Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModel.cs (.../StochasticSoilModel.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -22,17 +22,15 @@ using System; using System.Collections.Generic; using System.Linq; -using Core.Common.Base; using Core.Common.Base.Geometry; -using Ringtoets.Piping.Primitives; namespace Ringtoets.Piping.Data { /// /// This class represents a stochastic soil model which consists out of a collection of . /// A stochastic soil model contains a segment for which the model applies. /// - public class StochasticSoilModel : Observable + public class StochasticSoilModel { /// /// Creates a new instance of . @@ -83,11 +81,10 @@ /// Thrown when /// is null. /// Thrown when - /// contains multiple with the same - /// , and also contains a - /// with the same name. + /// contains multiple profiles with the same name, and also contains a + /// profile with the same name. /// - public void Update(StochasticSoilModel fromModel) + public StochasticSoilModelProfileDifference Update(StochasticSoilModel fromModel) { if (fromModel == null) { @@ -101,21 +98,35 @@ { Geometry.Add(point); } - List newNames = new List(); + + var newNames = new List(); + var updatedProfiles = new List(); + var addedProfiles = new List(); + var removedProfiles = new List(); + foreach (var fromProfile in fromModel.StochasticSoilProfiles) { var sameProfile = StochasticSoilProfiles.SingleOrDefault(sp => sp.SoilProfile.Name.Equals(fromProfile.SoilProfile.Name)); if (sameProfile != null) { sameProfile.Update(fromProfile); + updatedProfiles.Add(sameProfile); } else { - StochasticSoilProfiles.Add(fromProfile); + StochasticSoilProfiles.Add(fromProfile); + addedProfiles.Add(fromProfile); } newNames.Add(fromProfile.SoilProfile.Name); } - StochasticSoilProfiles.RemoveAll(sp => !newNames.Contains(sp.SoilProfile.Name)); + + foreach (var profileToRemove in StochasticSoilProfiles.Where(sp => !newNames.Contains(sp.SoilProfile.Name)).ToList()) + { + StochasticSoilProfiles.Remove(profileToRemove); + removedProfiles.Add(profileToRemove); + } + + return new StochasticSoilModelProfileDifference(addedProfiles, updatedProfiles, removedProfiles); } public override string ToString() Index: Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModelProfileDifference.cs =================================================================== diff -u --- Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModelProfileDifference.cs (revision 0) +++ Ringtoets/Piping/src/Ringtoets.Piping.Data/StochasticSoilModelProfileDifference.cs (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -0,0 +1,63 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System.Collections.Generic; + +namespace Ringtoets.Piping.Data +{ + /// + /// Container for the differences of the collection of contained + /// by a . + /// + public class StochasticSoilModelProfileDifference + { + /// + /// Creates a new instance of . + /// + /// Profiles that were added to the model. + /// Profiles that were updated. + /// Profiles that were removed from the model. + public StochasticSoilModelProfileDifference( + ICollection addedProfiles, + ICollection updatedProfiles, + ICollection removedProfiles) + { + AddedProfiles = addedProfiles; + UpdatedProfiles = updatedProfiles; + RemovedProfiles = removedProfiles; + } + + /// + /// Gets the profiles that were updated. + /// + public ICollection UpdatedProfiles { get; } + + /// + /// Gets the profiles that were removed from the model. + /// + public ICollection RemovedProfiles { get; } + + /// + /// Gets the profiles that were added to the model. + /// + public ICollection AddedProfiles { get; } + } +} \ No newline at end of file Index: Ringtoets/Piping/src/Ringtoets.Piping.Forms/Views/PipingInputView.cs =================================================================== diff -u -r08ae1e1f03d86959cbcec3692983183faaa42b6b -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Forms/Views/PipingInputView.cs (.../PipingInputView.cs) (revision 08ae1e1f03d86959cbcec3692983183faaa42b6b) +++ Ringtoets/Piping/src/Ringtoets.Piping.Forms/Views/PipingInputView.cs (.../PipingInputView.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -39,7 +39,6 @@ { private readonly Observer calculationObserver; private readonly Observer calculationInputObserver; - private readonly Observer stochasticSoilModelObserver; private readonly ChartDataCollection soilProfileChartData; private readonly ChartLineData surfaceLineChartData; @@ -69,7 +68,6 @@ calculationObserver = new Observer(UpdateChartTitle); calculationInputObserver = new Observer(UpdateViewData); - stochasticSoilModelObserver = new Observer(UpdateViewData); chartDataCollection = new ChartDataCollection(RingtoetsCommonFormsResources.Calculation_Input); soilProfileChartData = PipingChartDataFactory.CreateSoilProfileChartData(); @@ -109,7 +107,6 @@ calculationObserver.Observable = data; calculationInputObserver.Observable = data?.InputParameters; - stochasticSoilModelObserver.Observable = data?.InputParameters.StochasticSoilModel; if (data == null) { Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/StochasticSoilModelUpdateData.cs =================================================================== diff -u -r673bf2f4f4de6006444aae3a10183f9442eb0f23 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/StochasticSoilModelUpdateData.cs (.../StochasticSoilModelUpdateData.cs) (revision 673bf2f4f4de6006444aae3a10183f9442eb0f23) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/StochasticSoilModelUpdateData.cs (.../StochasticSoilModelUpdateData.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -25,6 +25,7 @@ using Core.Common.Base; using log4net; using Ringtoets.Piping.Data; +using Ringtoets.Piping.Service; namespace Ringtoets.Piping.Plugin.FileImporter { @@ -34,8 +35,22 @@ public class StochasticSoilModelUpdateData : IStochasticSoilModelUpdateStrategy { private readonly ILog log = LogManager.GetLogger(typeof(StochasticSoilModelUpdateData)); + private readonly PipingFailureMechanism failureMechanism; /// + /// Creates a new instance of . + /// + /// The failure mechanism in which the models are updated. + public StochasticSoilModelUpdateData(PipingFailureMechanism failureMechanism) + { + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + this.failureMechanism = failureMechanism; + } + + /// /// Updates the . /// Updates stochastic soil models in that are part of /// . @@ -69,25 +84,48 @@ throw new ArgumentNullException(nameof(targetCollection)); } - var updatedModels = new List(); + var removedModels = targetCollection.ToList(); + var updatedOrAddedModels = new List(); + var affectedObjects = new List { targetCollection }; foreach (var readModel in readStochasticSoilModels) { var existingModel = targetCollection.SingleOrDefault(existing => existing.Name.Equals(readModel.Name)); if (existingModel != null) { - existingModel.Update(readModel); - updatedModels.Add(existingModel); + StochasticSoilModelProfileDifference difference = existingModel.Update(readModel); + RemoveStochasticSoilProfilesFromInputs(difference, affectedObjects); + + removedModels.Remove(existingModel); + updatedOrAddedModels.Add(existingModel); } else { - updatedModels.Add(readModel); + removedModels.Remove(readModel); + updatedOrAddedModels.Add(readModel); } } + foreach (var model in removedModels) + { + RemoveStochasticSoilModel(model, affectedObjects); + } targetCollection.Clear(); - targetCollection.AddRange(updatedModels, sourceFilePath); + targetCollection.AddRange(updatedOrAddedModels, sourceFilePath); - return new IObservable[] { targetCollection }.Union(updatedModels); + return affectedObjects; } + + private void RemoveStochasticSoilModel(StochasticSoilModel removedModel, List affectedObjects) + { + affectedObjects.AddRange(PipingDataSynchronizationService.RemoveStochasticSoilModel(failureMechanism, removedModel)); + } + + private void RemoveStochasticSoilProfilesFromInputs(StochasticSoilModelProfileDifference difference, List affectedObjects) + { + foreach (StochasticSoilProfile removedProfile in difference.RemovedProfiles) + { + affectedObjects.AddRange(PipingDataSynchronizationService.RemoveStochasticSoilProfileFromInput(failureMechanism, removedProfile)); + } + } } } \ No newline at end of file Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingPlugin.cs =================================================================== diff -u -r673bf2f4f4de6006444aae3a10183f9442eb0f23 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingPlugin.cs (.../PipingPlugin.cs) (revision 673bf2f4f4de6006444aae3a10183f9442eb0f23) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingPlugin.cs (.../PipingPlugin.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -497,7 +497,9 @@ return (nodeData, parentData, treeViewControl) => Gui.Get(nodeData, treeViewControl) .AddImportItem() .AddCustomItem( - CreateUpdateStochasticSoilModelsItem(nodeData.WrappedData)) + CreateUpdateStochasticSoilModelsItem( + nodeData.WrappedData, + nodeData.FailureMechanism)) .AddSeparator() .AddDeleteChildrenItem() .AddSeparator() @@ -506,22 +508,22 @@ .Build(); } - private StrictContextMenuItem CreateUpdateStochasticSoilModelsItem(StochasticSoilModelCollection nodeDataWrappedData) + private StrictContextMenuItem CreateUpdateStochasticSoilModelsItem(StochasticSoilModelCollection soilModelCollection, PipingFailureMechanism failureMechanism) { return new StrictContextMenuItem( "&Bijwerken...", "Werk de reeds bekende lijst van stochastische ondergrondmodellen bij.", PipingPluginResources.RefreshIcon, (sender, args) => { - var importer = new StochasticSoilModelImporter(nodeDataWrappedData, - nodeDataWrappedData.SourcePath, - new StochasticSoilModelUpdateData()); + var importer = new StochasticSoilModelImporter(soilModelCollection, + soilModelCollection.SourcePath, + new StochasticSoilModelUpdateData(failureMechanism)); var activity = new FileImportActivity(importer, "Bijwerken van stochastische ondergrondmodellen."); ActivityProgressDialogRunner.Run(Gui.MainWindow, activity); }) { - Enabled = nodeDataWrappedData.SourcePath != null + Enabled = soilModelCollection.SourcePath != null }; } Index: Ringtoets/Piping/src/Ringtoets.Piping.Service/PipingDataSynchronizationService.cs =================================================================== diff -u -rb2b9fdf365e70928a05c57966eeed30d9050e528 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/src/Ringtoets.Piping.Service/PipingDataSynchronizationService.cs (.../PipingDataSynchronizationService.cs) (revision b2b9fdf365e70928a05c57966eeed30d9050e528) +++ Ringtoets/Piping/src/Ringtoets.Piping.Service/PipingDataSynchronizationService.cs (.../PipingDataSynchronizationService.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -220,6 +220,43 @@ return changedObservables; } + /// + /// Removes a given from calculations in the + /// and clears all data that depends on it, either directly or indirectly. + /// + /// The failure mechanism containing . + /// The soil profile residing in + /// that should be removed. + /// All observable objects affected by this method. + /// Thrown when + /// or is null. + public static IEnumerable RemoveStochasticSoilProfileFromInput(PipingFailureMechanism failureMechanism, StochasticSoilProfile soilProfile) + { + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + if (soilProfile == null) + { + throw new ArgumentNullException(nameof(soilProfile)); + } + + var changedObservables = new List(); + + IEnumerable pipingCalculationScenarios = + failureMechanism.Calculations + .Cast() + .Where(pcs => ReferenceEquals(pcs.InputParameters.StochasticSoilProfile, soilProfile)); + + foreach (PipingCalculation pipingCalculationScenario in pipingCalculationScenarios) + { + changedObservables.AddRange(RingtoetsCommonDataSynchronizationService.ClearCalculationOutput(pipingCalculationScenario)); + changedObservables.AddRange(ClearStochasticSoilProfile(pipingCalculationScenario.InputParameters)); + } + + return changedObservables; + } + private static IEnumerable ClearSurfaceLine(PipingInput input) { input.SurfaceLine = null; @@ -240,6 +277,16 @@ }; } + private static IEnumerable ClearStochasticSoilProfile(PipingInput input) + { + input.StochasticSoilProfile = null; + + return new[] + { + input + }; + } + private static IEnumerable ClearHydraulicBoundaryLocation(PipingInput input) { if (input.HydraulicBoundaryLocation != null) Index: Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/StochasticSoilModelUpdateDataTest.cs =================================================================== diff -u -r673bf2f4f4de6006444aae3a10183f9442eb0f23 -r89d34600d1408c8b1f4240020e841ba64cc26622 --- Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/StochasticSoilModelUpdateDataTest.cs (.../StochasticSoilModelUpdateDataTest.cs) (revision 673bf2f4f4de6006444aae3a10183f9442eb0f23) +++ Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/StochasticSoilModelUpdateDataTest.cs (.../StochasticSoilModelUpdateDataTest.cs) (revision 89d34600d1408c8b1f4240020e841ba64cc26622) @@ -33,20 +33,31 @@ public class StochasticSoilModelUpdateDataTest { [Test] - public void DefaultConstructor_CreatesNewInstance() + public void Constructor_WithoutCalculations_CreatesNewInstance() { // Call - var strategy = new StochasticSoilModelUpdateData(); + TestDelegate test = () => new StochasticSoilModelUpdateData(null); // Assert + string paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("failureMechanism", paramName); + } + + [Test] + public void Constructor_WithCalculations_CreatesNewInstance() + { + // Call + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); + + // Assert Assert.IsInstanceOf(strategy); } [Test] public void UpdateModelWithImportedData_ReadStochasticSoilModelsNull_ThrowsArgumentNullException() { // Setup - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call TestDelegate test = () => strategy.UpdateModelWithImportedData(null, string.Empty, new StochasticSoilModelCollection()); @@ -60,7 +71,7 @@ public void UpdateModelWithImportedData_SourceFilePathNull_ThrowsArgumentNullException() { // Setup - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call TestDelegate test = () => strategy.UpdateModelWithImportedData(new List(), null, new StochasticSoilModelCollection()); @@ -74,7 +85,7 @@ public void UpdateModelWithImportedData_TargetCollectionNull_ThrowsArgumentNullException() { // Setup - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call TestDelegate test = () => strategy.UpdateModelWithImportedData(new List(), string.Empty, null); @@ -98,7 +109,7 @@ new TestStochasticSoilModel(nonUniqueName) }, sourceFilePath); - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); var importedStochasticSoilModels = new[] { new TestStochasticSoilModel(nonUniqueName) @@ -120,7 +131,7 @@ new TestStochasticSoilModel(), new TestStochasticSoilModel() }; - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); var targetCollection = new StochasticSoilModelCollection(); // Call @@ -142,7 +153,7 @@ new TestStochasticSoilModel() }, sourceFilePath); - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call strategy.UpdateModelWithImportedData(new List(), sourceFilePath, targetCollection); @@ -165,7 +176,7 @@ existingModel, }, sourceFilePath); - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call strategy.UpdateModelWithImportedData(new[] { readModel }, sourceFilePath, targetCollection); @@ -189,15 +200,13 @@ existingModel, }, sourceFilePath); - var strategy = new StochasticSoilModelUpdateData(); + var strategy = new StochasticSoilModelUpdateData(new PipingFailureMechanism()); // Call strategy.UpdateModelWithImportedData(new[] { readModel }, sourceFilePath, targetCollection); // Assert Assert.AreSame(existingModel, targetCollection.First()); } - - private void NotifyProgress(string stepName, int stepNr, int totalNr) {} } } \ No newline at end of file