// Copyright (C) Stichting Deltares 2017. 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; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Core.Common.Base.Geometry; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.FailureMechanism; namespace Ringtoets.Common.Util { /// /// Utility class for data synchronization of the /// of objects. /// public static class AssignUnassignCalculations { /// /// Update objects with the . /// /// The objects which contain the /// information about assigning calculations to sections. /// All the currently known calculations to try and match with section results. /// All affected objects by the update. /// Thrown when any input parameter is null. /// Thrown when or /// contains a null element. public static IEnumerable Update( IEnumerable sectionResults, IEnumerable calculations) { ValidateSectionResults(sectionResults); ValidateCalculations(calculations); SectionResultWithCalculationAssignment[] sectionResultsArray = sectionResults.ToArray(); IDictionary> calculationsPerSegmentName = CollectCalculationsPerSection(sectionResultsArray.Select(sr => sr.Result.Section), calculations); return UnassignCalculationInAllSectionResultsAndAssignSingleRemainingCalculation( sectionResultsArray, calculationsPerSegmentName); } /// /// Determine which objects are available for a /// . /// /// The objects. /// The objects. /// A containing a /// of objects /// for each section name which has calculations. /// Thrown when any input parameter is null. /// Thrown when or /// contains a null element. public static IDictionary> CollectCalculationsPerSection( IEnumerable sections, IEnumerable calculations) { ValidateSections(sections); ValidateCalculations(calculations); SectionSegments[] sectionSegments = SectionSegmentsHelper.MakeSectionSegments(sections); var calculationsPerSegment = new Dictionary>(); foreach (CalculationWithLocation calculationWithLocation in calculations) { FailureMechanismSection section = FindSectionAtLocation(sectionSegments, calculationWithLocation.Location); if (section == null) { continue; } UpdateCalculationsOfSegment(calculationsPerSegment, section.Name, calculationWithLocation.Calculation); } return calculationsPerSegment; } /// /// Determine which geometrically contains the . /// /// The objects /// whose are considered. /// The . /// The containing , or null. /// Thrown when any input parameter is null or when /// an element in is null. /// Thrown when contains a null element. public static FailureMechanismSection FailureMechanismSectionForCalculation( IEnumerable sections, CalculationWithLocation calculation) { ValidateSections(sections); ValidateCalculationWithLocation(calculation); SectionSegments[] sectionSegments = SectionSegmentsHelper.MakeSectionSegments(sections); return FindSectionAtLocation(sectionSegments, calculation.Location); } private static IEnumerable UnassignCalculationInAllSectionResultsAndAssignSingleRemainingCalculation( IEnumerable sectionResults, IDictionary> calculationsPerSegmentName) { var affectedObjects = new Collection(); foreach (SectionResultWithCalculationAssignment sectionResult in sectionResults) { string sectionName = sectionResult.Result.Section.Name; var affected = false; if (!calculationsPerSegmentName.ContainsKey(sectionName)) { sectionResult.Calculation = null; affected = true; } if (calculationsPerSegmentName.ContainsKey(sectionName)) { IEnumerable calculationsInCurrentSection = calculationsPerSegmentName[sectionName]; if (!calculationsInCurrentSection.Contains(sectionResult.Calculation)) { sectionResult.Calculation = null; affected = true; } if (sectionResult.Calculation == null && calculationsInCurrentSection.Count() == 1) { sectionResult.Calculation = calculationsInCurrentSection.Single(); affected = true; } } if (affected) { affectedObjects.Add(sectionResult.Result); } } return affectedObjects; } private static FailureMechanismSection FindSectionAtLocation(IEnumerable sectionSegmentsCollection, Point2D location) { return SectionSegmentsHelper.GetSectionForPoint(sectionSegmentsCollection, location); } private static void UpdateCalculationsOfSegment(IDictionary> calculationsPerSegment, string sectionName, ICalculation calculation) { if (!calculationsPerSegment.ContainsKey(sectionName)) { calculationsPerSegment.Add(sectionName, new List()); } calculationsPerSegment[sectionName].Add(calculation); } #region Validate inputs private static void ValidateSections(IEnumerable sections) { if (sections == null) { throw new ArgumentNullException(nameof(sections)); } if (sections.Any(s => s == null)) { throw new ArgumentException(@"Sections contains an entry without value.", nameof(sections)); } } private static void ValidateCalculationWithLocation(CalculationWithLocation calculation) { if (calculation == null) { throw new ArgumentNullException(nameof(calculation)); } } private static void ValidateCalculations(IEnumerable calculations) { if (calculations == null) { throw new ArgumentNullException(nameof(calculations)); } if (calculations.Any(s => s == null)) { throw new ArgumentException(@"Calculations contains an entry without value.", nameof(calculations)); } } private static void ValidateSectionResults(IEnumerable sectionResults) { if (sectionResults == null) { throw new ArgumentNullException(nameof(sectionResults)); } if (sectionResults.Any(s => s == null)) { throw new ArgumentException(@"SectionResults contains an entry without value.", nameof(sectionResults)); } } #endregion } }