Index: Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.Designer.cs =================================================================== diff -u -r825be662d2c1a10b0156cf47ddbfde4e9ab9ee49 -r4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c --- Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 825be662d2c1a10b0156cf47ddbfde4e9ab9ee49) +++ Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -714,5 +714,23 @@ return ResourceManager.GetString("WmtsCapability_MapLayer_Title", resourceCulture); } } + + /// + /// Looks up a localized string similar to Het is niet mogelijk om een WMTS connectie aan te maken.. + /// + public static string WmtsConnectionInfoReader_Unable_To_Create_WmtsConnectionInfo { + get { + return ResourceManager.GetString("WmtsConnectionInfoReader_Unable_To_Create_WmtsConnectionInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to waarbij Naam='{0}' en URL='{1}'. + /// + public static string WmtsConnectionInfoReader_XML_Location_Name_0_URL_1 { + get { + return ResourceManager.GetString("WmtsConnectionInfoReader_XML_Location_Name_0_URL_1", resourceCulture); + } + } } } Index: Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.resx =================================================================== diff -u -r825be662d2c1a10b0156cf47ddbfde4e9ab9ee49 -r4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c --- Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.resx (.../Resources.resx) (revision 825be662d2c1a10b0156cf47ddbfde4e9ab9ee49) +++ Ringtoets/Integration/src/Ringtoets.Integration.Forms/Properties/Resources.resx (.../Resources.resx) (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -327,4 +327,10 @@ Coördinatenstelsel + + Het is niet mogelijk om een WMTS connectie aan te maken. + + + waarbij Naam='{0}' en URL='{1}' + \ No newline at end of file Index: Ringtoets/Integration/src/Ringtoets.Integration.Forms/WmtsConnectionInfoReader.cs =================================================================== diff -u -r41837216a2f3d66c3084500f4dcef57c478bfef5 -r4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c --- Ringtoets/Integration/src/Ringtoets.Integration.Forms/WmtsConnectionInfoReader.cs (.../WmtsConnectionInfoReader.cs) (revision 41837216a2f3d66c3084500f4dcef57c478bfef5) +++ Ringtoets/Integration/src/Ringtoets.Integration.Forms/WmtsConnectionInfoReader.cs (.../WmtsConnectionInfoReader.cs) (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -21,9 +21,15 @@ using System; using System.Collections.Generic; +using System.IO; using System.Xml; using System.Xml.Linq; +using Core.Common.IO.Exceptions; using Core.Common.Utils; +using Core.Common.Utils.Builders; +using log4net; +using Ringtoets.Integration.Forms.Properties; +using CoreCommonUtilsResources = Core.Common.Utils.Properties.Resources; namespace Ringtoets.Integration.Forms { @@ -32,54 +38,84 @@ /// public class WmtsConnectionInfoReader { + private static readonly ILog log = LogManager.GetLogger(typeof(WmtsConnectionInfoReader)); + private string filePath; + /// - /// Reads the WMTS Connection infos from . + /// Reads the WMTS Connection info objects from . /// - /// The file path that contains the information. - /// Thrown when is invalid. + /// The file path that contains the information. + /// Thrown when is invalid. + /// Thrown when could not successfully be read. /// A valid path: /// /// is not empty or null, /// does not consist out of only whitespace characters, /// does not contain an invalid character, /// does not end with a directory or path separator (empty file name). /// - public List ReadWmtsConnectionInfos(string filePath) + public IEnumerable ReadWmtsConnectionInfos(string path) { + filePath = path; + ValidateFilePath(); + + try + { + return ReadWmtsConnectionInfos(); + } + catch (Exception exception) when (exception is XmlException || exception is IOException) + { + string message = new FileReaderErrorMessageBuilder(filePath) + .Build(CoreCommonUtilsResources.Error_General_IO_Import_ErrorMessage); + throw new CriticalFileReadException(message, exception); + } + } + + private void ValidateFilePath() + { IOUtils.ValidateFilePath(filePath); + if (!File.Exists(filePath)) + { + string message = new FileReaderErrorMessageBuilder(filePath).Build(CoreCommonUtilsResources.Error_File_does_not_exist); + throw new CriticalFileReadException(message); + } + } + private IEnumerable ReadWmtsConnectionInfos() + { var connectionInfos = new List(); using (XmlReader reader = XmlReader.Create(filePath)) { while (reader.Read()) { - if (reader.NodeType != XmlNodeType.Element || !reader.IsStartElement() || reader.Name != WmtsConnectionInfoXmlDefinitions.WmtsConnectionElement) + if (reader.NodeType != XmlNodeType.Element + || !reader.IsStartElement() + || reader.Name != WmtsConnectionInfoXmlDefinitions.WmtsConnectionElement) { continue; } - connectionInfos.Add(ReadWmtsConnectionElement(reader)); + WmtsConnectionInfo readWmtsConnectionElement = ReadWmtsConnectionElement(reader); + if (readWmtsConnectionElement != null) + { + connectionInfos.Add(readWmtsConnectionElement); + } } } return connectionInfos; } - private static WmtsConnectionInfo ReadWmtsConnectionElement(XmlReader reader) + private WmtsConnectionInfo ReadWmtsConnectionElement(XmlReader reader) { using (XmlReader subtreeReader = reader.ReadSubtree()) { XElement wmtsConnectionElement = XElement.Load(subtreeReader); - WmtsConnectionInfo readWmtsConnectionInfo = WmtsConnectionInfo(wmtsConnectionElement); - if (readWmtsConnectionInfo != null) - { - return readWmtsConnectionInfo; - } + return WmtsConnectionInfo(wmtsConnectionElement); } - return null; } - private static WmtsConnectionInfo WmtsConnectionInfo(XContainer element) + private WmtsConnectionInfo WmtsConnectionInfo(XContainer element) { XElement nameElement = element.Element(WmtsConnectionInfoXmlDefinitions.WmtsConnectionNameElement); XElement urlElement = element.Element(WmtsConnectionInfoXmlDefinitions.WmtsConnectionUrlElement); @@ -88,7 +124,25 @@ { return null; } - return new WmtsConnectionInfo(nameElement.Value, urlElement.Value); + + return TryCreateWmtsConnectionInfo(nameElement.Value, urlElement.Value); } + + private WmtsConnectionInfo TryCreateWmtsConnectionInfo(string name, string url) + { + try + { + return new WmtsConnectionInfo(name, url); + } + catch (ArgumentException exception) + { + string locationDescription = string.Format(Resources.WmtsConnectionInfoReader_XML_Location_Name_0_URL_1, name, url); + string message = new FileReaderErrorMessageBuilder(filePath).WithLocation(locationDescription) + .Build(Resources.WmtsConnectionInfoReader_Unable_To_Create_WmtsConnectionInfo); + + log.Warn(message, exception); + } + return null; + } } } \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/WmtsConnectionInfoReaderTest.cs =================================================================== diff -u -r41837216a2f3d66c3084500f4dcef57c478bfef5 -r4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/WmtsConnectionInfoReaderTest.cs (.../WmtsConnectionInfoReaderTest.cs) (revision 41837216a2f3d66c3084500f4dcef57c478bfef5) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/WmtsConnectionInfoReaderTest.cs (.../WmtsConnectionInfoReaderTest.cs) (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -20,8 +20,10 @@ // All rights reserved. using System; -using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Xml; +using Core.Common.IO.Exceptions; using Core.Common.TestUtil; using NUnit.Framework; @@ -86,17 +88,33 @@ } [Test] + public void ReadWmtsConnectionInfos_FileMissing_ThrowsCriticalFileReadException() + { + // Setup + string filePath = Path.Combine(testPath, Path.GetRandomFileName()); + var reader = new WmtsConnectionInfoReader(); + + // Call + TestDelegate call = () => reader.ReadWmtsConnectionInfos(filePath); + + // Assert + var expectedMessage = $"Fout bij het lezen van bestand '{filePath}': het bestand bestaat niet."; + string actualMessage = Assert.Throws(call).Message; + Assert.AreEqual(expectedMessage, actualMessage); + } + + [Test] public void ReadWmtsConnectionInfos_FileWithTwoWmtsConnectionInfos_ReturnsExpectedWmtsConnectionInfos() { // Setup string filePath = Path.Combine(testPath, "twoValidWmtsConnectionInfos.txt"); var reader = new WmtsConnectionInfoReader(); // Call - List readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath); + WmtsConnectionInfo[] readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); // Assert - Assert.AreEqual(2, readConnectionInfos.Count); + Assert.AreEqual(2, readConnectionInfos.Length); var firstExpected = new WmtsConnectionInfo(@"Actueel Hoogtebestand Nederland (AHN1)", @"https://geodata.nationaalgeoregister.nl/tiles/service/wmts/ahn1?request=GetCapabilities"); var secondExpected = new WmtsConnectionInfo(@"Zeegraskartering", @"https://geodata.nationaalgeoregister.nl/zeegraskartering/wfs?request=GetCapabilities"); @@ -112,17 +130,133 @@ var reader = new WmtsConnectionInfoReader(); // Call - List readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath); + WmtsConnectionInfo[] readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); // Assert - Assert.AreEqual(2, readConnectionInfos.Count); + Assert.AreEqual(2, readConnectionInfos.Length); var firstExpected = new WmtsConnectionInfo(@"Actueel Hoogtebestand Nederland (AHN1)", @"https://geodata.nationaalgeoregister.nl/tiles/service/wmts/ahn1?request=GetCapabilities"); var secondExpected = new WmtsConnectionInfo(@"Zeegraskartering", @"https://geodata.nationaalgeoregister.nl/zeegraskartering/wfs?request=GetCapabilities"); AssertAreEqual(firstExpected, readConnectionInfos[0]); AssertAreEqual(secondExpected, readConnectionInfos[1]); } + [Test] + public void ReadWmtsConnectionInfos_FileWithoutWmtsConnectionInfos_ReturnsEmptyList() + { + // Setup + string filePath = Path.Combine(testPath, "WmtsConnectionInfosZeroWmtsConnections.txt"); + var reader = new WmtsConnectionInfoReader(); + + // Call + WmtsConnectionInfo[] readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); + + // Assert + Assert.AreEqual(0, readConnectionInfos.Length); + } + + [Test] + public void ReadWmtsConnectionInfos_FileWithoutWmtsConnectionsElement_ThrowsCriticalFileReadException() + { + // Setup + string filePath = Path.Combine(testPath, "WmtsConnectionInfosWithoutWmtsConnectionsElement.txt"); + var reader = new WmtsConnectionInfoReader(); + + // Call + TestDelegate call = () => reader.ReadWmtsConnectionInfos(filePath); + + // Assert + var exception = Assert.Throws(call); + string expectedMessage = $"Fout bij het lezen van bestand '{filePath}': het bestand " + + "kon niet worden geopend. Mogelijk is het bestand corrupt " + + "of in gebruik door een andere applicatie."; + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + + [Test] + public void ReadWmtsConnectionInfos_FileEmptyUrlElement_WarnsAndReadsRestOfFile() + { + // Setup + string filePath = Path.Combine(testPath, "twoWmtsConnectionInfosOneEmptyUrl.txt"); + var reader = new WmtsConnectionInfoReader(); + + WmtsConnectionInfo[] readConnectionInfos = null; + + // Call + Action action = () => { readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); }; + + // Assert + string expectedMessage = $"Fout bij het lezen van bestand '{filePath}' waarbij Naam='First name' " + + "en URL='': het is niet mogelijk om een WMTS connectie aan te maken."; + TestHelper.AssertLogMessageWithLevelIsGenerated(action, Tuple.Create(expectedMessage, LogLevelConstant.Warn)); + + Assert.IsNotNull(readConnectionInfos); + Assert.AreEqual(1, readConnectionInfos.Length); + var expectedWmtsConnectionInfo = new WmtsConnectionInfo(@"second name", + @"https://domain.com"); + + AssertAreEqual(expectedWmtsConnectionInfo, readConnectionInfos[0]); + } + + [Test] + public void ReadWmtsConnectionInfos_FileMissingOneUrlElement_SkipdAndReadsRestOfFile() + { + // Setup + string filePath = Path.Combine(testPath, "twoWmtsConnectionInfosOneWithoutUrlElement.txt"); + var reader = new WmtsConnectionInfoReader(); + + // Call + WmtsConnectionInfo[] readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); + + // Assert + Assert.AreEqual(1, readConnectionInfos.Length); + var expectedWmtsConnectionInfo = new WmtsConnectionInfo(@"second name", @"https://domain.com"); + + AssertAreEqual(expectedWmtsConnectionInfo, readConnectionInfos[0]); + } + + [Test] + public void ReadWmtsConnectionInfos_FileMissingOneNameElement_SkipdAndReadsRestOfFile() + { + // Setup + string filePath = Path.Combine(testPath, "twoWmtsConnectionInfosOneWithoutNameElement.txt"); + var reader = new WmtsConnectionInfoReader(); + + // Call + WmtsConnectionInfo[] readConnectionInfos = reader.ReadWmtsConnectionInfos(filePath).ToArray(); + + // Assert + Assert.AreEqual(1, readConnectionInfos.Length); + var expectedWmtsConnectionInfo = new WmtsConnectionInfo(@"second name", @"https://domain.com"); + + AssertAreEqual(expectedWmtsConnectionInfo, readConnectionInfos[0]); + } + + [Test] + public void ReadWmtsConnectionInfos_FileLocked_ThrowsCriticalFileReadException() + { + // Setup + string filePath = Path.Combine(testPath, Path.GetRandomFileName()); + var reader = new WmtsConnectionInfoReader(); + + using (var fileDisposeHelper = new FileDisposeHelper(filePath)) + { + fileDisposeHelper.LockFiles(); + + // Call + TestDelegate call = () => reader.ReadWmtsConnectionInfos(filePath); + + // Assert + var exception = Assert.Throws(call); + string expectedMessage = $"Fout bij het lezen van bestand '{filePath}': het bestand " + + "kon niet worden geopend. Mogelijk is het bestand corrupt " + + "of in gebruik door een andere applicatie."; + Assert.AreEqual(expectedMessage, exception.Message); + Assert.IsInstanceOf(exception.InnerException); + } + } + private static void AssertAreEqual(WmtsConnectionInfo expected, WmtsConnectionInfo actual) { Assert.AreEqual(expected.Name, actual.Name); Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosWithoutWmtsConnectionsElement.txt =================================================================== diff -u --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosWithoutWmtsConnectionsElement.txt (revision 0) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosWithoutWmtsConnectionsElement.txt (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -0,0 +1 @@ + \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosZeroWmtsConnections.txt =================================================================== diff -u --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosZeroWmtsConnections.txt (revision 0) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/WmtsConnectionInfosZeroWmtsConnections.txt (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -0,0 +1 @@ + \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneEmptyUrl.txt =================================================================== diff -u --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneEmptyUrl.txt (revision 0) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneEmptyUrl.txt (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -0,0 +1 @@ +First namesecond namehttps://domain.com \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutNameElement.txt =================================================================== diff -u --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutNameElement.txt (revision 0) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutNameElement.txt (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -0,0 +1 @@ +First URLsecond namehttps://domain.com \ No newline at end of file Index: Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutUrlElement.txt =================================================================== diff -u --- Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutUrlElement.txt (revision 0) +++ Ringtoets/Integration/test/Ringtoets.Integration.Forms.Test/test-data/WmtsConnectionInfo/twoWmtsConnectionInfosOneWithoutUrlElement.txt (revision 4f2d8bc47cb1935643c427e0d3bd69a06bddaa7c) @@ -0,0 +1 @@ +First namesecond namehttps://domain.com \ No newline at end of file