Index: Ringtoets/Integration/src/Ringtoets.Integration.IO/Exporters/HydraulicBoundaryLocationsExporter.cs =================================================================== diff -u -re6b8ed51afc1debd1e378a93287434e49a88d0b9 -r7da1d7b169c200fb9bd3080296d94eaae1471585 --- Ringtoets/Integration/src/Ringtoets.Integration.IO/Exporters/HydraulicBoundaryLocationsExporter.cs (.../HydraulicBoundaryLocationsExporter.cs) (revision e6b8ed51afc1debd1e378a93287434e49a88d0b9) +++ Ringtoets/Integration/src/Ringtoets.Integration.IO/Exporters/HydraulicBoundaryLocationsExporter.cs (.../HydraulicBoundaryLocationsExporter.cs) (revision 7da1d7b169c200fb9bd3080296d94eaae1471585) @@ -21,8 +21,12 @@ using System; using Core.Common.Base.IO; +using Core.Common.IO.Exceptions; using Core.Common.Util; +using log4net; using Ringtoets.Common.Data.AssessmentSection; +using Ringtoets.Common.Util; +using RingtoetsCommonIOResources = Ringtoets.Common.IO.Properties.Resources; namespace Ringtoets.Integration.IO.Exporters { @@ -31,6 +35,7 @@ /// public class HydraulicBoundaryLocationsExporter : IFileExporter { + private static readonly ILog log = LogManager.GetLogger(typeof(HydraulicBoundaryLocationsExporter)); private readonly IAssessmentSection assessmentSection; private readonly string filePath; @@ -57,7 +62,19 @@ public bool Export() { - throw new NotImplementedException(); + try + { + HydraulicBoundaryLocationsWriter.WriteHydraulicBoundaryLocations( + AggregatedHydraulicBoundaryLocationFactory.CreateAggregatedHydraulicBoundaryLocations(assessmentSection), + filePath); + } + catch (CriticalFileWriteException e) + { + log.ErrorFormat(RingtoetsCommonIOResources.HydraulicBoundaryLocationsExporter_Error_Exception_0_no_HydraulicBoundaryLocations_exported, e.Message); + return false; + } + + return true; } } } \ No newline at end of file Index: Ringtoets/Integration/src/Ringtoets.Integration.IO/Ringtoets.Integration.IO.csproj =================================================================== diff -u -re6b8ed51afc1debd1e378a93287434e49a88d0b9 -r7da1d7b169c200fb9bd3080296d94eaae1471585 --- Ringtoets/Integration/src/Ringtoets.Integration.IO/Ringtoets.Integration.IO.csproj (.../Ringtoets.Integration.IO.csproj) (revision e6b8ed51afc1debd1e378a93287434e49a88d0b9) +++ Ringtoets/Integration/src/Ringtoets.Integration.IO/Ringtoets.Integration.IO.csproj (.../Ringtoets.Integration.IO.csproj) (revision 7da1d7b169c200fb9bd3080296d94eaae1471585) @@ -7,6 +7,10 @@ + + ..\..\..\..\packages\log4net.2.0.4\lib\net40-full\log4net.dll + True + @@ -19,6 +23,7 @@ Copying.licenseheader + @@ -52,6 +57,11 @@ Ringtoets.Common.Data False + + {52ba7627-cbab-4209-be77-3b5f31378277} + Ringtoets.Common.IO + False + {6A074D65-A81C-4C1C-8E24-F36C916E4ED7} Ringtoets.Common.Util Index: Ringtoets/Integration/src/Ringtoets.Integration.IO/packages.config =================================================================== diff -u --- Ringtoets/Integration/src/Ringtoets.Integration.IO/packages.config (revision 0) +++ Ringtoets/Integration/src/Ringtoets.Integration.IO/packages.config (revision 7da1d7b169c200fb9bd3080296d94eaae1471585) @@ -0,0 +1,26 @@ + + + + + \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Exporters/HydraulicBoundaryLocationsExporterTest.cs =================================================================== diff -u -re6b8ed51afc1debd1e378a93287434e49a88d0b9 -r7da1d7b169c200fb9bd3080296d94eaae1471585 --- Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Exporters/HydraulicBoundaryLocationsExporterTest.cs (.../HydraulicBoundaryLocationsExporterTest.cs) (revision e6b8ed51afc1debd1e378a93287434e49a88d0b9) +++ Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Exporters/HydraulicBoundaryLocationsExporterTest.cs (.../HydraulicBoundaryLocationsExporterTest.cs) (revision 7da1d7b169c200fb9bd3080296d94eaae1471585) @@ -21,11 +21,15 @@ using System; using System.IO; +using System.Linq; +using System.Security.AccessControl; using Core.Common.Base.IO; using Core.Common.TestUtil; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.AssessmentSection; +using Ringtoets.Common.Data.Hydraulics; +using Ringtoets.Common.Data.TestUtil; using Ringtoets.Integration.IO.Exporters; namespace Ringtoets.Integration.IO.Test.Exporters @@ -80,5 +84,106 @@ Assert.IsInstanceOf(exporter); mocks.VerifyAll(); } + + [Test] + public void Export_ValidData_ReturnsTrueAndWritesCorrectData() + { + // Setup + var assessmentSection = new ObservableTestAssessmentSectionStub(); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + new HydraulicBoundaryLocation(123, "aName", 1.1, 2.2) + }); + + string directoryPath = TestHelper.GetScratchPadPath("Export_ValidData_ReturnTrue"); + Directory.CreateDirectory(directoryPath); + string filePath = Path.Combine(directoryPath, "test.shp"); + const string baseName = "test"; + + var exporter = new HydraulicBoundaryLocationsExporter(assessmentSection, filePath); + + // Precondition + AssertEssentialShapefileExists(directoryPath, baseName, false); + + try + { + // Call + bool isExported = exporter.Export(); + + // Assert + AssertEssentialShapefileExists(directoryPath, baseName, true); + AssertEssentialShapefileMd5Hashes(directoryPath, baseName); + Assert.IsTrue(isExported); + } + finally + { + Directory.Delete(directoryPath, true); + } + } + + [Test] + public void Export_InvalidDirectoryRights_LogErrorAndReturnFalse() + { + // Setup + var assessmentSection = new ObservableTestAssessmentSectionStub(); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + new HydraulicBoundaryLocation(123, "aName", 1.1, 2.2) + }); + + string directoryPath = TestHelper.GetScratchPadPath("Export_InvalidDirectoryRights_LogErrorAndReturnFalse"); + Directory.CreateDirectory(directoryPath); + string filePath = Path.Combine(directoryPath, "test.shp"); + + var exporter = new HydraulicBoundaryLocationsExporter(assessmentSection, filePath); + + try + { + using (new DirectoryPermissionsRevoker(directoryPath, FileSystemRights.Write)) + { + // Call + var isExported = true; + Action call = () => isExported = exporter.Export(); + + // Assert + string expectedMessage = $"Er is een onverwachte fout opgetreden tijdens het schrijven van het bestand '{filePath}'. " + + "Er zijn geen hydraulische randvoorwaarden locaties geëxporteerd."; + TestHelper.AssertLogMessageIsGenerated(call, expectedMessage); + Assert.IsFalse(isExported); + } + } + finally + { + Directory.Delete(directoryPath, true); + } + } + + private static void AssertEssentialShapefileExists(string directoryPath, string baseName, bool shouldExist) + { + string pathName = Path.Combine(directoryPath, baseName); + Assert.AreEqual(shouldExist, File.Exists(pathName + ".shp")); + Assert.AreEqual(shouldExist, File.Exists(pathName + ".shx")); + Assert.AreEqual(shouldExist, File.Exists(pathName + ".dbf")); + } + + private static void AssertEssentialShapefileMd5Hashes(string directoryPath, string baseName) + { + string refPathName = Path.Combine(TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.IO), + nameof(HydraulicBoundaryLocationsExporter), "ExpectedExport"); + string pathName = Path.Combine(directoryPath, baseName); + + AssertBinaryFileContent(refPathName, pathName, ".shp", 100, 28); + AssertBinaryFileContent(refPathName, pathName, ".shx", 100, 8); + AssertBinaryFileContent(refPathName, pathName, ".dbf", 32, 741); + } + + private static void AssertBinaryFileContent(string refPathName, string pathName, string extension, int headerLength, int bodyLength) + { + byte[] refContent = File.ReadAllBytes(refPathName + extension); + byte[] content = File.ReadAllBytes(pathName + extension); + Assert.AreEqual(headerLength + bodyLength, content.Length); + Assert.AreEqual(refContent.Skip(headerLength).Take(bodyLength), + content.Skip(headerLength).Take(bodyLength)); + } } } \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Ringtoets.Integration.IO.Test.csproj =================================================================== diff -u -re6b8ed51afc1debd1e378a93287434e49a88d0b9 -r7da1d7b169c200fb9bd3080296d94eaae1471585 --- Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Ringtoets.Integration.IO.Test.csproj (.../Ringtoets.Integration.IO.Test.csproj) (revision e6b8ed51afc1debd1e378a93287434e49a88d0b9) +++ Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/Ringtoets.Integration.IO.Test.csproj (.../Ringtoets.Integration.IO.Test.csproj) (revision 7da1d7b169c200fb9bd3080296d94eaae1471585) @@ -48,6 +48,10 @@ {6A074D65-A81C-4C1C-8E24-F36C916E4ED7} Ringtoets.Common.Util + + {4843D6E5-066F-4795-94F5-1D53932DD03C} + Ringtoets.Common.Data.TestUtil + {54DF6303-BF9A-4AE9-BE09-4AF50EF27412} Ringtoets.Common.Util.TestUtil Index: Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/test-data/HydraulicBoundaryLocationsExporter/ExpectedExport.dbf =================================================================== diff -u Binary files differ Index: Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/test-data/HydraulicBoundaryLocationsExporter/ExpectedExport.shp =================================================================== diff -u Binary files differ Index: Ringtoets/Integration/test/Ringtoets.Integration.IO.Test/test-data/HydraulicBoundaryLocationsExporter/ExpectedExport.shx =================================================================== diff -u Binary files differ