Index: Ringtoets/Integration/src/Ringtoets.Integration.Service/Comparers/AssessmentSectionMergeComparer.cs
===================================================================
diff -u
--- Ringtoets/Integration/src/Ringtoets.Integration.Service/Comparers/AssessmentSectionMergeComparer.cs (revision 0)
+++ Ringtoets/Integration/src/Ringtoets.Integration.Service/Comparers/AssessmentSectionMergeComparer.cs (revision 48b3f7c813c181320c85aa269973dac65f0d1d68)
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Core.Common.Base.Geometry;
+using Ringtoets.Common.Data.AssessmentSection;
+using Ringtoets.Common.Data.Contribution;
+using Ringtoets.Common.Data.Hydraulics;
+
+namespace Ringtoets.Integration.Service.Comparers
+{
+ ///
+ /// Class which compares to
+ /// determine whether they are equal and can be used to merged.
+ ///
+ public class AssessmentSectionMergeComparer : IAssessmentSectionMergeComparer
+ {
+ public bool Compare(IAssessmentSection referenceAssessmentSection, IAssessmentSection assessmentSectionToCompare)
+ {
+ if (referenceAssessmentSection == null)
+ {
+ throw new ArgumentNullException(nameof(referenceAssessmentSection));
+ }
+
+ if (assessmentSectionToCompare == null)
+ {
+ throw new ArgumentNullException(nameof(assessmentSectionToCompare));
+ }
+
+ return referenceAssessmentSection.Id == assessmentSectionToCompare.Id
+ && referenceAssessmentSection.Composition == assessmentSectionToCompare.Composition
+ && AreReferenceLinesEquivalent(referenceAssessmentSection.ReferenceLine, assessmentSectionToCompare.ReferenceLine)
+ && AreHydraulicBoundaryDatabasesEquivalent(referenceAssessmentSection.HydraulicBoundaryDatabase, assessmentSectionToCompare.HydraulicBoundaryDatabase)
+ && AreFailureMechanismContributionsEquivalent(referenceAssessmentSection.FailureMechanismContribution, assessmentSectionToCompare.FailureMechanismContribution);
+ }
+
+ private static bool AreReferenceLinesEquivalent(ReferenceLine referenceLine, ReferenceLine otherReferenceLine)
+ {
+ if (referenceLine == null && otherReferenceLine == null)
+ {
+ return true;
+ }
+
+ IEnumerable referenceLineGeometry = referenceLine?.Points;
+ IEnumerable otherReferenceLineGeometry = otherReferenceLine?.Points;
+
+ if (referenceLineGeometry == null || otherReferenceLineGeometry == null)
+ {
+ return false;
+ }
+
+ int nrOfPoints = referenceLineGeometry.Count();
+ if (otherReferenceLineGeometry.Count() != nrOfPoints)
+ {
+ return false;
+ }
+
+ for (var i = 0; i < nrOfPoints; i++)
+ {
+ if (!referenceLineGeometry.ElementAt(i).Equals(otherReferenceLineGeometry.ElementAt(i)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool AreHydraulicBoundaryDatabasesEquivalent(HydraulicBoundaryDatabase hydraulicBoundaryDatabase,
+ HydraulicBoundaryDatabase otherHydraulicBoundaryDatabase)
+ {
+ return hydraulicBoundaryDatabase.Version == otherHydraulicBoundaryDatabase.Version;
+ }
+
+ private static bool AreFailureMechanismContributionsEquivalent(FailureMechanismContribution failureMechanismContribution,
+ FailureMechanismContribution otherFailureMechanismContribution)
+ {
+ return AreNormsEquivalent(failureMechanismContribution.LowerLimitNorm, otherFailureMechanismContribution.LowerLimitNorm)
+ && AreNormsEquivalent(failureMechanismContribution.SignalingNorm, otherFailureMechanismContribution.SignalingNorm)
+ && failureMechanismContribution.NormativeNorm == otherFailureMechanismContribution.NormativeNorm;
+ }
+
+ private static bool AreNormsEquivalent(double norm, double otherNorm)
+ {
+ return Math.Abs(norm - otherNorm) < 1e-5;
+ }
+ }
+}
\ No newline at end of file
Index: Ringtoets/Integration/src/Ringtoets.Integration.Service/Ringtoets.Integration.Service.csproj
===================================================================
diff -u -r66626f5c114e03e5aad4ec0e4e1400dd43608fb6 -r48b3f7c813c181320c85aa269973dac65f0d1d68
--- Ringtoets/Integration/src/Ringtoets.Integration.Service/Ringtoets.Integration.Service.csproj (.../Ringtoets.Integration.Service.csproj) (revision 66626f5c114e03e5aad4ec0e4e1400dd43608fb6)
+++ Ringtoets/Integration/src/Ringtoets.Integration.Service/Ringtoets.Integration.Service.csproj (.../Ringtoets.Integration.Service.csproj) (revision 48b3f7c813c181320c85aa269973dac65f0d1d68)
@@ -11,6 +11,7 @@
+
Index: Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Comparers/AssessmentSectionMergeComparerTest.cs
===================================================================
diff -u
--- Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Comparers/AssessmentSectionMergeComparerTest.cs (revision 0)
+++ Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Comparers/AssessmentSectionMergeComparerTest.cs (revision 48b3f7c813c181320c85aa269973dac65f0d1d68)
@@ -0,0 +1,222 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Core.Common.Base;
+using Core.Common.Base.Geometry;
+using Core.Common.TestUtil;
+using NUnit.Framework;
+using Rhino.Mocks;
+using Ringtoets.Common.Data;
+using Ringtoets.Common.Data.AssessmentSection;
+using Ringtoets.Common.Data.Contribution;
+using Ringtoets.Common.Data.FailureMechanism;
+using Ringtoets.Common.Data.Hydraulics;
+using Ringtoets.Integration.Service.Comparers;
+
+namespace Ringtoets.Integration.Service.Test.Comparers
+{
+ [TestFixture]
+ public class AssessmentSectionMergeComparerTest
+ {
+ [Test]
+ public void Constructor_ExpectedValues()
+ {
+ // Call
+ var comparer = new AssessmentSectionMergeComparer();
+
+ // Assert
+ Assert.IsInstanceOf(comparer);
+ }
+
+ [Test]
+ public void Compare_ReferenceAssessmentSectionNull_ThrowsArgumentNullException()
+ {
+ // Setup
+ var mocks = new MockRepository();
+ var assessmentSectionToCompare = mocks.Stub();
+ mocks.ReplayAll();
+
+ var comparer = new AssessmentSectionMergeComparer();
+
+ // Call
+ TestDelegate call = () => comparer.Compare(null, assessmentSectionToCompare);
+
+ // Assert
+ var exception = Assert.Throws(call);
+ Assert.AreEqual("referenceAssessmentSection", exception.ParamName);
+
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void Compare_AssessmentSectionToCompareNull_ThrowsArgumentNullException()
+ {
+ // Setup
+ var mocks = new MockRepository();
+ var referenceAssessmentSection = mocks.Stub();
+ mocks.ReplayAll();
+
+ var comparer = new AssessmentSectionMergeComparer();
+
+ // Call
+ TestDelegate call = () => comparer.Compare(referenceAssessmentSection, null);
+
+ // Assert
+ var exception = Assert.Throws(call);
+ Assert.AreEqual("assessmentSectionToCompare", exception.ParamName);
+
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void Compare_AssessmentSectionsAreEqual_ReturnsTrue()
+ {
+ // Setup
+ IAssessmentSection referenceAssessmentSection = CreateAssessmentSection();
+ IAssessmentSection assessmentSectionToCompare = CreateAssessmentSection();
+
+ var comparer = new AssessmentSectionMergeComparer();
+
+ // Call
+ bool result = comparer.Compare(referenceAssessmentSection, assessmentSectionToCompare);
+
+ // Assert
+ Assert.IsTrue(result);
+ }
+
+ [Test]
+ [TestCaseSource(nameof(GetUnequalTestCases))]
+ public void Compare_AssessmentSectionsUnequalFailureMechanismContributions_ReturnsFalse(
+ IAssessmentSection assessmentSection)
+ {
+ // Setup
+ IAssessmentSection referenceAssessmentSection = CreateAssessmentSection();
+
+ var comparer = new AssessmentSectionMergeComparer();
+
+ // Call
+ bool result = comparer.Compare(referenceAssessmentSection, assessmentSection);
+
+ // Assert
+ Assert.IsFalse(result);
+ }
+
+ private static IAssessmentSection CreateAssessmentSection()
+ {
+ var referenceLine = new ReferenceLine();
+ referenceLine.SetGeometry(new []
+ {
+ new Point2D(1, 1),
+ new Point2D(1, 2)
+ });
+ return new TestAssessmentSection("Id", AssessmentSectionComposition.Dike)
+ {
+ ReferenceLine = referenceLine
+ };
+ }
+
+ private static IEnumerable GetUnequalTestCases()
+ {
+ IAssessmentSection referenceAssessmentSection = CreateAssessmentSection();
+ yield return new TestCaseData(new TestAssessmentSection("DifferentId", referenceAssessmentSection.Composition))
+ .SetName("ID");
+ yield return new TestCaseData(new TestAssessmentSection(referenceAssessmentSection.Id, AssessmentSectionComposition.DikeAndDune))
+ .SetName("Composition");
+
+ foreach (ChangePropertyData changeSingleDataProperty in ChangeSingleDataProperties())
+ {
+ IAssessmentSection assessmentSection = CreateAssessmentSection();
+ changeSingleDataProperty.ActionToChangeProperty(assessmentSection);
+ yield return new TestCaseData(assessmentSection).SetName(changeSingleDataProperty.PropertyName);
+ }
+ }
+
+ private static IEnumerable> ChangeSingleDataProperties()
+ {
+ var referenceLineDifferentPointCount = new ReferenceLine();
+ referenceLineDifferentPointCount.SetGeometry(new[]
+ {
+ new Point2D(1, 1)
+ });
+ yield return new ChangePropertyData(sec => sec.ReferenceLine = referenceLineDifferentPointCount,
+ "Referenceline different point count");
+ yield return new ChangePropertyData(sec => sec.ReferenceLine = null,
+ "Referenceline null");
+
+ var referenceLineDifferentPoint = new ReferenceLine();
+ referenceLineDifferentPoint.SetGeometry(new[]
+ {
+ new Point2D(1, 1),
+ new Point2D(1, 3)
+ });
+ yield return new ChangePropertyData(sec => sec.ReferenceLine = referenceLineDifferentPoint,
+ "Referenceline different point");
+
+ yield return new ChangePropertyData(sec => sec.HydraulicBoundaryDatabase.Version = "DifferentVersion",
+ "HydraulicBoundaryDataBase");
+ yield return new ChangePropertyData(sec => sec.FailureMechanismContribution.LowerLimitNorm = sec.FailureMechanismContribution.LowerLimitNorm - 0.05,
+ "LowerLimitNorm");
+ yield return new ChangePropertyData(sec => sec.FailureMechanismContribution.SignalingNorm = sec.FailureMechanismContribution.SignalingNorm - 0.005,
+ "SignalingNorm");
+ yield return new ChangePropertyData(sec => sec.FailureMechanismContribution.NormativeNorm = sec.FailureMechanismContribution.NormativeNorm == NormType.LowerLimit
+ ? NormType.Signaling
+ : NormType.LowerLimit,
+ "NormType");
+ }
+
+ private class TestAssessmentSection : IAssessmentSection
+ {
+ public TestAssessmentSection(string id, AssessmentSectionComposition composition)
+ {
+ Id = id;
+ Composition = composition;
+ FailureMechanismContribution = new FailureMechanismContribution(Enumerable.Empty(), 0, 0.1, 0.025);
+ HydraulicBoundaryDatabase = new HydraulicBoundaryDatabase();
+ }
+
+ public IEnumerable Observers { get; }
+
+ public void Attach(IObserver observer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Detach(IObserver observer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void NotifyObservers()
+ {
+ throw new NotImplementedException();
+ }
+
+ public string Id { get; }
+ public string Name { get; set; }
+ public Comment Comments { get; }
+ public AssessmentSectionComposition Composition { get; }
+ public ReferenceLine ReferenceLine { get; set; }
+ public FailureMechanismContribution FailureMechanismContribution { get; }
+ public HydraulicBoundaryDatabase HydraulicBoundaryDatabase { get; }
+ public BackgroundData BackgroundData { get; }
+ public IObservableEnumerable WaterLevelCalculationsForFactorizedSignalingNorm { get; }
+ public IObservableEnumerable WaterLevelCalculationsForSignalingNorm { get; }
+ public IObservableEnumerable WaterLevelCalculationsForLowerLimitNorm { get; }
+ public IObservableEnumerable WaterLevelCalculationsForFactorizedLowerLimitNorm { get; }
+ public IObservableEnumerable WaveHeightCalculationsForFactorizedSignalingNorm { get; }
+ public IObservableEnumerable WaveHeightCalculationsForSignalingNorm { get; }
+ public IObservableEnumerable WaveHeightCalculationsForLowerLimitNorm { get; }
+ public IObservableEnumerable WaveHeightCalculationsForFactorizedLowerLimitNorm { get; }
+
+ public IEnumerable GetFailureMechanisms()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ChangeComposition(AssessmentSectionComposition newComposition)
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
\ No newline at end of file
Index: Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Ringtoets.Integration.Service.Test.csproj
===================================================================
diff -u -r4376a372caaaeb42bf19c90fbf1cc012e56766ea -r48b3f7c813c181320c85aa269973dac65f0d1d68
--- Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Ringtoets.Integration.Service.Test.csproj (.../Ringtoets.Integration.Service.Test.csproj) (revision 4376a372caaaeb42bf19c90fbf1cc012e56766ea)
+++ Ringtoets/Integration/test/Ringtoets.Integration.Service.Test/Ringtoets.Integration.Service.Test.csproj (.../Ringtoets.Integration.Service.Test.csproj) (revision 48b3f7c813c181320c85aa269973dac65f0d1d68)
@@ -19,6 +19,7 @@
+
@@ -33,6 +34,10 @@
{3bbfd65b-b277-4e50-ae6d-bd24c3434609}
Core.Common.Base
+
+ {D749EE4C-CE50-4C17-BF01-9A953028C126}
+ Core.Common.TestUtil
+
{C6309704-D67B-434C-BC98-9F8910BC1D10}
Ringtoets.ClosingStructures.Data