// Copyright (C) Stichting Deltares 2023. All rights reserved. // // This file is part of the application DAM - UI. // // DAM - UI 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.Linq; using Deltares.Dam.Data.CsvImporters; using Deltares.Dam.Data.Importers; using Deltares.Maps; using GeoAPI.Geometries; using NetTopologySuite.Geometries; using NUnit.Framework; using Rhino.Mocks; namespace Deltares.Dam.Tests.Importers { [TestFixture] public class LineAttributeImporterTest { private MockRepository mocks; private IFeatureRepository crossSectionRepository, attributesRepository; private Feature crossSection, attributeLine, outsideLine; private LineAttributeImporter importer; #region Fixture Setup/Teardown [SetUp] public void FixtureSetup() { mocks = new MockRepository(); } [TearDown] public void FixtureTearDown() { } #endregion #region Setup/Teardown [SetUp] public void TestSetup() { importer = new LineAttributeImporter(); crossSectionRepository = mocks.DynamicMock(); attributesRepository = mocks.DynamicMock(); crossSection = Feature.Create(new LineString(new[] { new Coordinate(-1, 0), new Coordinate(1, 0) })); attributeLine = Feature.Create(new LineString(new[] { new Coordinate(0, -1), new Coordinate(0, 1) })); // this line should not touch outsideLine = Feature.Create(new LineString(new[] { new Coordinate(10, -1), new Coordinate(10, 1) })); } [TearDown] public void TestTearDown() { } #endregion [Test] public void Import_NoRepositorySet_Throws() { Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("No repository set")); } [Test] public void Import_NoAttributesInRepository_Throws() { importer.AttributeRepository = new FeatureRepository(); Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("The repository doesn't contain attributes")); } [Test] public void Import_LocationIDEmpty_Throws() { importer.AttributeRepository = new FeatureRepository(); importer.AttributeRepository.Add(Feature.Create(0,0, new[]{ new KeyValuePair("test", 0) })); importer.LocationIDAttributeName = ""; Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("The location ID attribute name is not valid")); } [Test] public void Import_LocationIDNull_Throws() { importer.AttributeRepository = new FeatureRepository(); importer.AttributeRepository.Add(Feature.Create(0, 0, new[] { new KeyValuePair("test", 0) })); importer.LocationIDAttributeName = null; Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("The location ID attribute name is not valid")); } [Test] public void Import_LocationIDWhiteSpace_Throws() { importer.AttributeRepository = new FeatureRepository(); importer.AttributeRepository.Add(Feature.Create(0, 0, new[] { new KeyValuePair("test", 0) })); importer.LocationIDAttributeName = " "; Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("The location ID attribute name is not valid")); } [Test] public void Import_NoCrossSectionSet_Throws() { importer.AttributeRepository = new FeatureRepository(); importer.AttributeRepository.Add(Feature.Create(0, 0, new[] { new KeyValuePair("test", 0) })); importer.LocationIDAttributeName = "Test"; Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("No cross section repository set")); } [Test] public void Import_NoAttributeMappingListSet_Throws() { importer.AttributeRepository = new FeatureRepository(); importer.AttributeRepository.Add(Feature.Create(0, 0, new[] { new KeyValuePair("test", 0) })); importer.CrossSectionRepository = new FeatureRepository(); importer.LocationIDAttributeName = "Test"; Assert.That(() => importer.Import(), Throws.InvalidOperationException.With.Message.EqualTo("No attribute mappings set")); } [Test] [Category("Integration")] public void PerformanceOfImport_UsingSmallList_IsAcceptable() { const string crossSectionFile = @"..\..\..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\Crosssection.shp"; const string attributeFile = @"..\..\..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\DampingFactorPL3.shp"; var locations = new List { new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0010" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0020" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0030" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0040" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0050" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0060" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0070" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0080" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0090" }, new CsvImporterLocations.LocationRecord { LocationId = "TPL_Hempolder_0100" } }; var crossSections = FeatureRepository.CreateFromShapeFile(crossSectionFile); var attributes = FeatureRepository.CreateFromShapeFile(attributeFile); var crossSectionMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.CrossSectionAttributId); importer.LocationIDAttributeName = crossSectionMapping.Name; importer.Targets = locations; importer.CrossSectionRepository = crossSections; importer.AttributeRepository = attributes; var mapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.DampingFactorPl3AttributeId); importer.AttributeMappings = new[] { mapping }; importer.Import(); } [Test] public void Import_IntersectionFoundBetweenCrossSectionAndAttributeLine_ValuesFromAttributeLineAreSetOnTarget() { const string locationID = "Test_Location_01"; const double expectedValue = 5.7; CsvImporterLocations.LocationRecord location = new CsvImporterLocations.LocationRecord { LocationId = locationID }; importer.Targets = new[] { location }; importer.CrossSectionRepository = crossSectionRepository; importer.AttributeRepository = attributesRepository; var crossSectionMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.CrossSectionAttributId); this.crossSection.AddAttribute(crossSectionMapping.Name, locationID); Expect.Call(crossSectionRepository.Features).Return(new[] { this.crossSection }); importer.LocationIDAttributeName = crossSectionMapping.Name; var trafLoadMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.TrafficLoadAttributeId); importer.AttributeMappings = new[] { trafLoadMapping }; this.attributeLine.AddAttribute(trafLoadMapping.Name, expectedValue); Expect.Call(attributesRepository.Query((IFeature)null)).IgnoreArguments().Return(new[] { this.attributeLine }); Expect.Call(attributesRepository.SupportedAttributes).Return(new[] { LocationShapeFileAttributeMap.TrafficLoadAttributeId }); mocks.ReplayAll(); importer.Import(); Assert.AreEqual(expectedValue, location.TrafficLoad); } [Test] public void Import_NoIntersectionFoundBetweenCrossSectionAndOutsideLine_ValuesFromAttributeLineAreNotSetOnTarget() { const string locationID = "Test_Location_02"; const double expectedValue = 5.7; CsvImporterLocations.LocationRecord location = new CsvImporterLocations.LocationRecord { LocationId = locationID, TrafficLoad = expectedValue }; importer.Targets = new[] { location }; importer.CrossSectionRepository = crossSectionRepository; importer.AttributeRepository = attributesRepository; var crossSectionMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.CrossSectionAttributId); this.crossSection.AddAttribute(crossSectionMapping.Name, locationID); Expect.Call(crossSectionRepository.Features).Return(new[] { this.crossSection }); importer.LocationIDAttributeName = crossSectionMapping.Name; var trafLoadMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.TrafficLoadAttributeId); importer.AttributeMappings = new[] { trafLoadMapping }; this.attributeLine.AddAttribute(trafLoadMapping.Name, expectedValue); Expect.Call(attributesRepository.Query((IFeature)null)).IgnoreArguments().Return(new[] { this.outsideLine }); Expect.Call(attributesRepository.SupportedAttributes).Return(new[] { LocationShapeFileAttributeMap.TrafficLoadAttributeId }); mocks.ReplayAll(); importer.Import(); Assert.AreEqual(expectedValue, location.TrafficLoad); } [Test] public void Import_NoIntersectionFoundBetweenCrossSectionAndOutsideLine_ExceptionIsAdded() { const string locationID = "Test_Location_02"; const double expectedValue = 5.7; CsvImporterLocations.LocationRecord location = new CsvImporterLocations.LocationRecord { LocationId = locationID, TrafficLoad = expectedValue }; importer.Targets = new[] { location }; importer.CrossSectionRepository = crossSectionRepository; importer.AttributeRepository = attributesRepository; var crossSectionMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.CrossSectionAttributId); this.crossSection.AddAttribute(crossSectionMapping.Name, locationID); Expect.Call(crossSectionRepository.Features).Return(new[] { this.crossSection }); importer.LocationIDAttributeName = crossSectionMapping.Name; var trafLoadMapping = LocationShapeFileAttributeMap.GetAttributeMapping(LocationShapeFileAttributeMap.TrafficLoadAttributeId); importer.AttributeMappings = new[] { trafLoadMapping }; this.attributeLine.AddAttribute(trafLoadMapping.Name, expectedValue); Expect.Call(attributesRepository.Query((IFeature)null)).IgnoreArguments().Return(new[] { this.outsideLine }); Expect.Call(attributesRepository.SupportedAttributes).Return(new[] { LocationShapeFileAttributeMap.TrafficLoadAttributeId }); mocks.ReplayAll(); importer.Import(); Assert.IsTrue(importer.Errors.OfType().Count() == 1, "The NotSupported error was not added to the error list for logging when no intersections are found. "); } } }