Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision a483049c20ef6d26addd0718d0f31ae1922e6f49) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -12,7 +12,6 @@ { /// /// This class reads a SqLite database file and constructs from this database. - /// The database is created with the DSoilModel application. /// public class PipingSoilProfileReader : IDisposable { @@ -37,64 +36,53 @@ private SQLiteConnection connection; private SQLiteDataReader dataReader; + private readonly string databaseFileName; + private readonly string databaseRequiredVersion = "15.0.5.0"; + /// - /// Creates a new instance of which will use the - /// as its source. The reader will not point to any record at the start. Use to start reading + /// Creates a new instance of which will use the + /// as its source. The reader will not point to any record at the start. Use to start reading /// profiles. /// - /// The path of the database file to open. - public PipingSoilProfileReader(string dbFile) + /// The path of the database file to open. + public PipingSoilProfileReader(string databaseFilePath) { - if (String.IsNullOrEmpty(dbFile)) + if (String.IsNullOrEmpty(databaseFilePath)) { throw new ArgumentException(Resources.Error_PathMustBeSpecified); } - if (!File.Exists(dbFile)) + if (!File.Exists(databaseFilePath)) { - throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, dbFile)); + throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, databaseFilePath)); } - OpenConnection(dbFile); + databaseFileName = Path.GetFileName(databaseFilePath); + OpenConnection(databaseFilePath); + SetReaderToFirstRecord(); } /// + /// Gets the value true if profiles can be read using the . + /// false otherwise. + /// + public bool HasNext { get; private set; } + + /// /// Prepares the next layer from the database. /// /// False if there are no more rows to be read. True otherwise. - /// Thrown when reading the layer entry from the database failed. /// Thrown when parsing the geometry of a 2d soil layer failed. public PipingSoilProfile ReadProfile() { - if (dataReader == null) + if (!HasNext) { - throw new InvalidOperationException(GetType() + " was not initialized using Next()"); + throw new InvalidOperationException("Reader has reached the end and cannot read more profiles."); } - return TryRead(dimensionColumn) == 1 ? ReadPipingProfile1D().Build() : ReadPipingProfile2D().Build(); + var dimensionValue = Read(dimensionColumn); + return dimensionValue == 1 ? ReadPipingProfile1D().Build() : ReadPipingProfile2D().Build(); } - /// - /// Moves the reader to the next record in the database. - /// - /// true if there was another record. Otherwise, false. - /// You should never make two calls to this method without calling in between. - public bool Next() - { - InitializeReader(); - if (!dataReader.Read()) - { - if (dataReader.NextResult()) - { - return dataReader.Read(); - } - } - else - { - return true; - } - return false; - } - public void Dispose() { if (dataReader != null) @@ -105,64 +93,90 @@ connection.Dispose(); } + /// + /// Moves the reader to the next record in the database. + /// + private void MoveNext() + { + HasNext = dataReader.Read() || (dataReader.NextResult() && dataReader.Read()); + } + private ISoilProfileBuilder ReadPipingProfile1D() { - var profileName = TryRead(profileNameColumn); - var bottom = TryRead(bottomColumn); - var layerCount = TryRead(layerCountColumn); + var profileName = Read(profileNameColumn); + var layerCount = Read(layerCountColumn); + var bottom = Read(bottomColumn); + var soilProfileBuilder = new SoilProfileBuilder1D(profileName, bottom); - for (int i = 1; i <= layerCount; i++) + for (var i = 1; i <= layerCount; i++) { soilProfileBuilder.Add(ReadPipingSoilLayer()); - if (i < layerCount) - { - Next(); - } + MoveNext(); } + return soilProfileBuilder; } private ISoilProfileBuilder ReadPipingProfile2D() { - var profileName = TryRead(profileNameColumn); - var intersectionX = TryRead(intersectionXColumn); - var layerCount = TryRead(layerCountColumn); + var profileName = Read(profileNameColumn); + var layerCount = Read(layerCountColumn); + var intersectionX = Read(intersectionXColumn); + var soilProfileBuilder = new SoilProfileBuilder2D(profileName, intersectionX); for (int i = 1; i <= layerCount; i++) { - soilProfileBuilder.Add(ReadPiping2DSoilLayer()); - if (i < layerCount) + try { - Next(); + soilProfileBuilder.Add(ReadPiping2DSoilLayer()); } + catch (XmlException e) + { + var exception = new PipingSoilProfileReadException( + string.Format(Resources.PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_, i, profileName), e); + + while (i++ <= layerCount) + { + MoveNext(); + } + + throw exception; + } + MoveNext(); } + return soilProfileBuilder; } - private void InitializeReader() + private void SetReaderToFirstRecord() { - if (dataReader == null) - { - PrepareQueries(); - } + InitializeDataReader(); + MoveNext(); } - private T TryRead(string columnName) + private bool TryRead(string columnName, out T value) { try { - return (T) dataReader[columnName]; + value = (T) dataReader[columnName]; + return true; } catch (InvalidCastException e) { - throw new PipingSoilProfileReadException(String.Format(Resources.PipingSoilProfileReader_InvalidValueOnColumn, columnName), e); + value = default(T); + return false; } } + private T Read(string columnName) + { + return (T)dataReader[columnName]; + } + private void OpenConnection(string dbFile) { var connectionStringBuilder = new SQLiteConnectionStringBuilder @@ -191,28 +205,55 @@ private PipingSoilLayer ReadPipingSoilLayer() { - var columnValue = TryRead(topColumn); - var isAquiferValue = TryRead(isAquiferColumn); - var pipingSoilLayer = new PipingSoilLayer(columnValue) + double topValue; + double isAquiferValue; + + var columnValueRead = TryRead(topColumn, out topValue); + var isAquiferValueRead = TryRead(isAquiferColumn, out isAquiferValue); + + if (!columnValueRead || !isAquiferValueRead) { + return null; + } + + var pipingSoilLayer = new PipingSoilLayer(topValue) + { IsAquifer = isAquiferValue.Equals(1.0) }; return pipingSoilLayer; } private SoilLayer2D ReadPiping2DSoilLayer() { - var geometry = TryRead(layerGeometryColumn); - var isAquiferValue = TryRead(isAquiferColumn); + double isAquiferValue; + byte[] geometryValue; - SoilLayer2D pipingSoilLayer = new PipingSoilLayer2DReader(geometry).Read(); + var geometryRead = TryRead(layerGeometryColumn, out geometryValue); + var isAquiferValueRead = TryRead(isAquiferColumn, out isAquiferValue); + + if (!geometryRead || !isAquiferValueRead) + { + return null; + } + + SoilLayer2D pipingSoilLayer = new PipingSoilLayer2DReader(geometryValue).Read(); pipingSoilLayer.IsAquifer = isAquiferValue.Equals(1.0); return pipingSoilLayer; } - private void PrepareQueries() + /// + /// Prepares the two queries required for obtaining all the SoilProfile1D and SoilProfile2D with an x defined + /// to take an intersection from. Since two separate queries are used, the will + /// have two result sets which the method takes into account. + /// + private void InitializeDataReader() { + string versionQuery = string.Format( + "SELECT Value FROM _Metadata WHERE Key = 'VERSION' AND Value = '{0}';", + databaseRequiredVersion + ); + string materialPropertiesQuery = string.Format( string.Join(" ", "(SELECT", @@ -343,7 +384,7 @@ layer2DPropertiesQuery, mechanismParameterName); - dataReader = CreateDataReader(query2D + query1D, new SQLiteParameter + CreateDataReader(versionQuery + query2D + query1D, new SQLiteParameter { DbType = DbType.String, Value = pipingMechanismName, @@ -352,9 +393,9 @@ } /// - /// Creates a new data reader to use in this class, based on a query which returns all the known soil layers for which its profile has a X coordinate defined for piping. + /// Creates a new data reader to use in this class. /// - private SQLiteDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters) + private void CreateDataReader(string queryString, params SQLiteParameter[] parameters) { using (var query = new SQLiteCommand(connection) { @@ -365,13 +406,27 @@ try { - return query.ExecuteReader(); + dataReader = query.ExecuteReader(); + CheckVersion(); } catch (SQLiteException e) { - throw new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, connection.DataSource), e); + connection.Dispose(); + var exception = new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, databaseFileName), e); + throw exception; } } } + + private void CheckVersion() + { + if (!dataReader.HasRows) + { + throw new PipingSoilProfileReadException(String.Format( + Resources.PipingSoilProfileReader_DatabaseFileIncorrectVersions_Requires_0, + databaseRequiredVersion)); + } + dataReader.NextResult(); + } } } \ No newline at end of file Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision a483049c20ef6d26addd0718d0f31ae1922e6f49) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -196,6 +196,24 @@ } /// + /// Looks up a localized string similar to Kan de geometry van laag nummer '{0}' in profiel '{1}' niet interpreteren.. + /// + public static string PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_ { + get { + return ResourceManager.GetString("PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to De database heeft niet de vereiste versie informatie. Vereiste versie is: {0}.. + /// + public static string PipingSoilProfileReader_DatabaseFileIncorrectVersions_Requires_0 { + get { + return ResourceManager.GetString("PipingSoilProfileReader_DatabaseFileIncorrectVersions_Requires_0", resourceCulture); + } + } + + /// /// Looks up a localized string similar to Ondergrondprofiel in database bevat geen geldige waarde in kolom {0}.. /// public static string PipingSoilProfileReader_InvalidValueOnColumn { Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx (.../Resources.resx) (revision a483049c20ef6d26addd0718d0f31ae1922e6f49) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/Properties/Resources.resx (.../Resources.resx) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -183,4 +183,10 @@ Het bestand '{0}' heeft op regel {1} heeft geen ID. + + Kan de geometry van laag nummer '{0}' in profiel '{1}' niet interpreteren. + + + De database heeft niet de vereiste versie informatie. Vereiste versie is: {0}. + \ No newline at end of file Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/PipingSoilProfilesImporter.cs =================================================================== diff -u -r8df04aa7166563cc67a1b7e70f9f4b8867e454b7 -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/PipingSoilProfilesImporter.cs (.../PipingSoilProfilesImporter.cs) (revision 8df04aa7166563cc67a1b7e70f9f4b8867e454b7) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/FileImporter/PipingSoilProfilesImporter.cs (.../PipingSoilProfilesImporter.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -96,24 +96,27 @@ var importResult = ReadSoilProfiles(path); - if (!ShouldCancel) + if (!importResult.CriticalErrorOccurred) { - AddImportedDataToModel(target, importResult); + if (!ShouldCancel) + { + AddImportedDataToModel(target, importResult); + } + else + { + HandleUserCancellingImport(); + } } - else - { - HandleUserCancellingImport(); - } return target; } - private void AddImportedDataToModel(object target, IEnumerable importedSoilProfiles) + private void AddImportedDataToModel(object target, SoilProfilesReadResult importedSoilProfiles) { NotifyProgress(ApplicationResources.PipingSoilProfilesImporter_AddingImportedDataToModel, 2, 2); var targetCollection = (ICollection)target; - foreach (var soilProfile in importedSoilProfiles) + foreach (var soilProfile in importedSoilProfiles.ImportedSoilProfiles) { targetCollection.Add(soilProfile); } @@ -125,33 +128,40 @@ } } - private IEnumerable ReadSoilProfiles(string path) + private SoilProfilesReadResult ReadSoilProfiles(string path) { - using (var soilProfileReader = new PipingSoilProfileReader(path)) + var profiles = new Collection(); + PipingSoilProfileReader soilProfileReader = null; + + try { + soilProfileReader = new PipingSoilProfileReader(path); + } + catch (Exception e) + { + var message = string.Format(ApplicationResources.PipingSoilProfilesImporter_CriticalErrorReading_0_Cause_1_, + path, e.Message); + log.Error(message); + return new SoilProfilesReadResult(true); + } + + while (soilProfileReader.HasNext) + { try { - var profiles = new Collection(); - - while (soilProfileReader.Next()) - { - try - { - profiles.Add(soilProfileReader.ReadProfile()); - } - catch (Exception e) - { - log.Warn(e.Message); - } - } - return profiles; + profiles.Add(soilProfileReader.ReadProfile()); } catch (PipingSoilProfileReadException e) { - log.Error(e.Message); - return Enumerable.Empty(); + var message = string.Format(ApplicationResources.PipingSoilProfilesImporter_ReadSoilProfiles_File_0_Message_1_, + path, e.Message); + log.Error(message); } } + return new SoilProfilesReadResult(false) + { + ImportedSoilProfiles = profiles + }; } private void NotifyProgress(string currentStepName, int currentStep, int totalNumberOfSteps) @@ -166,5 +176,18 @@ { log.Info(ApplicationResources.PipingSoilProfilesImporter_ImportItem_ImportCancelled); } + + private class SoilProfilesReadResult + { + public SoilProfilesReadResult(bool errorOccurred) + { + CriticalErrorOccurred = errorOccurred; + ImportedSoilProfiles = new PipingSoilProfile[0]; + } + + public ICollection ImportedSoilProfiles { get; set; } + + public bool CriticalErrorOccurred { get; private set; } + } } } \ No newline at end of file Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.Designer.cs =================================================================== diff -u -ra950714ad9510756331d862aa35695fa0b2ed03b -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision a950714ad9510756331d862aa35695fa0b2ed03b) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -79,6 +79,15 @@ } /// + /// Looks up a localized string similar to Er is een fout opgetreden tijdens het inlezen van '{0}' waardoor import niet uitgevoerd kan worden: {1}. + /// + public static string PipingSoilProfilesImporter_CriticalErrorReading_0_Cause_1_ { + get { + return ResourceManager.GetString("PipingSoilProfilesImporter_CriticalErrorReading_0_Cause_1_", resourceCulture); + } + } + + /// /// Looks up a localized string similar to Grondprofielen importeren afgebroken. Geen data ingelezen.. /// public static string PipingSoilProfilesImporter_ImportItem_ImportCancelled { @@ -97,6 +106,15 @@ } /// + /// Looks up a localized string similar to Er is een leesfout opgetreden bij ondergrondprofiel van bestand '{0}' en is overgeslagen: {1}. + /// + public static string PipingSoilProfilesImporter_ReadSoilProfiles_File_0_Message_1_ { + get { + return ResourceManager.GetString("PipingSoilProfilesImporter_ReadSoilProfiles_File_0_Message_1_", resourceCulture); + } + } + + /// /// Looks up a localized string similar to Geïmporteerde data toevoegen aan faalmechanisme.... /// public static string PipingSurfaceLinesCsvImporter_AddingImportedDataToModel { Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.resx =================================================================== diff -u -ra950714ad9510756331d862aa35695fa0b2ed03b -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.resx (.../Resources.resx) (revision a950714ad9510756331d862aa35695fa0b2ed03b) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/Properties/Resources.resx (.../Resources.resx) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -165,4 +165,10 @@ Inlezen van de D-SoilModel database... + + Er is een fout opgetreden tijdens het inlezen van '{0}' waardoor import niet uitgevoerd kan worden: {1} + + + Er is een leesfout opgetreden bij ondergrondprofiel van bestand '{0}' en is overgeslagen: {1} + \ No newline at end of file Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs =================================================================== diff -u -rd73739bed38c7aaf880d1c57c8904f9667ee2329 -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs (.../PipingSoilProfileReaderTest.cs) (revision d73739bed38c7aaf880d1c57c8904f9667ee2329) +++ Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/PipingSoilProfileReaderTest.cs (.../PipingSoilProfileReaderTest.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -17,25 +17,53 @@ private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Piping.IO, "PipingSoilProfilesReader"); [Test] - public void ReadProfile_NextNotCalled_ThrowsInvalidOperationException() + public void Constructor_NonExistingPath_ThrowsFileNotFoundException() { // Setup - var testFile = "1dprofile.soil"; - var dbFile = Path.Combine(testDataPath, testFile); + var testFile = Path.Combine(testDataPath, "none.soil"); - using (var pipingSoilProfileReader = new PipingSoilProfileReader(dbFile)) - { - // Call - TestDelegate test = () => - { - pipingSoilProfileReader.ReadProfile(); - }; - // Assert - Assert.Throws(test); - } + // Call + TestDelegate test = () => new PipingSoilProfileReader(testFile); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_File_0_does_not_exist, testFile), exception.Message); } [Test] + [TestCase(null)] + [TestCase("")] + public void Constructor_FileNullOrEmpty_ThrowsArgumentException(string fileName) + { + // Call + TestDelegate test = () => new PipingSoilProfileReader(fileName); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(Resources.Error_PathMustBeSpecified, exception.Message); + } + + [Test] + [TestCase("text.txt")] + [TestCase("empty.soil")] + public void Constructor_IncorrectFormatFileOrInvalidSchema_ThrowsPipingSoilProfileReadException(string dbName) + { + // Setup + var dbFile = Path.Combine(testDataPath, dbName); + + // Precondition + Assert.IsTrue(FileHelper.CanOpenFileForWrite(dbFile), "Precondition: file can be opened for edits."); + + // Call + TestDelegate test = () => new PipingSoilProfileReader(dbFile); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual(String.Format(Resources.Error_SoilProfileReadFromDatabase, dbName), exception.Message); + Assert.IsTrue(FileHelper.CanOpenFileForWrite(dbFile)); + } + + [Test] public void ReadProfile_AfterDatabaseHasBeenRead_ThrowsInvalidOperationException() { // Setup @@ -44,41 +72,19 @@ using (var pipingSoilProfileReader = new PipingSoilProfileReader(dbFile)) { - while (pipingSoilProfileReader.Next()) + while (pipingSoilProfileReader.HasNext) { pipingSoilProfileReader.ReadProfile(); } // Call - TestDelegate test = () => - { - pipingSoilProfileReader.ReadProfile(); - }; + TestDelegate test = () => { pipingSoilProfileReader.ReadProfile(); }; // Assert Assert.Throws(test); } } [Test] - public void Next_InvalidSchema_ThrowsPipingSoilProfileReadException() - { - // Setup - var testFile = "empty.soil"; - var dbFile = Path.Combine(testDataPath, testFile); - - using (var pipingSoilProfileReader = new PipingSoilProfileReader(dbFile)) - { - // Call - TestDelegate test = () => - { - pipingSoilProfileReader.Next(); - }; - // Assert - Assert.Throws(test); - } - } - - [Test] public void Dispose_AfterConstruction_CorrectlyReleasesFile() { // Setup @@ -117,74 +123,20 @@ } [Test] - public void Constructor_NonExistingPath_ThrowsFileNotFoundException() - { - // Setup - var testFile = Path.Combine(testDataPath, "none.soil"); - - // Call - TestDelegate test = () => new PipingSoilProfileReader(testFile); - - // Assert - var exception = Assert.Throws(test); - Assert.AreEqual(String.Format(Resources.Error_File_0_does_not_exist, testFile), exception.Message); - } - - [Test] - [TestCase(null)] - [TestCase("")] - public void Constructor_FileNullOrEmpty_ThrowsArgumentException(string fileName) - { - // Call - TestDelegate test = () => new PipingSoilProfileReader(fileName); - - // Assert - var exception = Assert.Throws(test); - Assert.AreEqual(Resources.Error_PathMustBeSpecified, exception.Message); - } - - [Test] - public void Next_IncorrectFormatFile_ThrowsPipingSoilProfileReadException() - { - // Setup - var dbName = "text"; - var dbFile = Path.Combine(testDataPath, dbName + ".txt"); - - using (var pipingSoilProfileReader = new PipingSoilProfileReader(dbFile)) - { - // Call - TestDelegate test = () => pipingSoilProfileReader.Next(); - - // Assert - var exception = Assert.Throws(test); - Assert.AreEqual(String.Format(Resources.Error_SoilProfileReadFromDatabase, dbName), exception.Message); - } - } - - [Test] public void ReadProfile_DatabaseWith1DProfile3Layers_ReturnsProfile() { // Setup var testFile = "1dprofile.soil"; var dbFile = Path.Combine(testDataPath, testFile); var reader = new PipingSoilProfileReader(dbFile); + PipingSoilProfile profile; - var skipped = 0; + // Call - while (reader.Next()) - { - try - { - profile = reader.ReadProfile(); - } - catch (PipingSoilProfileReadException) - { - skipped++; - } - } + profile = reader.ReadProfile(); // Assert - Assert.AreEqual(0, skipped); + Assert.AreEqual(3,profile.Layers.Count()); } [Test] @@ -199,7 +151,7 @@ var result = new Collection(); // Call - while (pipingSoilProfilesReader.Next()) + while (pipingSoilProfilesReader.HasNext) { result.Add(pipingSoilProfilesReader.ReadProfile()); } @@ -211,21 +163,25 @@ } [Test] - public void Read_DatabaseWithNullValueForBottom_ThrowsPipingSoilProfileReadException() + public void Read_DatabaseProfileWithInvalid2dLayerGeometry_SkipsTheProfile() { // Setup - var testFile = "invalidbottom.soil"; + var testFile = "invalid2dGeometry.soil"; using (var pipingSoilProfilesReader = new PipingSoilProfileReader(Path.Combine(testDataPath, testFile))) { - pipingSoilProfilesReader.Next(); - // Call - TestDelegate test = () => pipingSoilProfilesReader.ReadProfile(); + TestDelegate profile = () => pipingSoilProfilesReader.ReadProfile(); + Func profile2 = () => pipingSoilProfilesReader.ReadProfile(); // Assert - var exception = Assert.Throws(test); - var message = String.Format(Resources.PipingSoilProfileReader_InvalidValueOnColumn, "Bottom"); + var exception = Assert.Throws(profile); + var message = String.Format(Resources.PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_, 1, "Profile"); Assert.AreEqual(message, exception.Message); + + var pipingSoilProfile = profile2(); + Assert.AreEqual("Profile2", pipingSoilProfile.Name); + Assert.AreEqual(3, pipingSoilProfile.Layers.Count()); + Assert.IsTrue(FileHelper.CanOpenFileForWrite(testFile)); } } @@ -266,21 +222,22 @@ { // Call var result = new Collection(); - var skippedProfiles = 0; + var skipped = 0; - while (pipingSoilProfilesReader.Next()) + while (pipingSoilProfilesReader.HasNext) { try { result.Add(pipingSoilProfilesReader.ReadProfile()); } catch { - skippedProfiles++; + skipped++; } } // Assert + Assert.AreEqual(0, skipped); Assert.AreEqual(1, result.Count); Assert.AreEqual(-2.1, result[0].Bottom); CollectionAssert.AreEqual(new[] @@ -302,7 +259,7 @@ ICollection result = new List(); int skipped = 0; - while (pipingSoilProfilesReader.Next()) + while (pipingSoilProfilesReader.HasNext) { try { @@ -379,7 +336,32 @@ CollectionAssert.AreEquivalent(new[] { - 9,8,8,6,6,5,5,6,4,4,3,3,7,7,7,5,5,5,6,6,4,5,4,4,2,3 + 9, + 8, + 8, + 6, + 6, + 5, + 5, + 6, + 4, + 4, + 3, + 3, + 7, + 7, + 7, + 5, + 5, + 5, + 6, + 6, + 4, + 5, + 4, + 4, + 2, + 3 }, result.Select(p => p.Layers.Count())); var firstProfile = result.FirstOrDefault(l => l.Name == "AD640M00_Segment_36005_1D1"); Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/TestHelpers/FileHelper.cs =================================================================== diff -u -ra950714ad9510756331d862aa35695fa0b2ed03b -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/TestHelpers/FileHelper.cs (.../FileHelper.cs) (revision a950714ad9510756331d862aa35695fa0b2ed03b) +++ Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/TestHelpers/FileHelper.cs (.../FileHelper.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -4,12 +4,12 @@ { public static class FileHelper { - public static bool CanOpenFileForWrite(string dbFile) + public static bool CanOpenFileForWrite(string pathToFile) { FileStream file = null; try { - file = File.OpenWrite(dbFile); + file = File.OpenWrite(pathToFile); return true; } catch (IOException) Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/test-data/PipingSoilProfilesReader/1dprofile.soil =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 Binary files differ Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/test-data/PipingSoilProfilesReader/combined1d2d.soil =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 Binary files differ Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/test-data/PipingSoilProfilesReader/emptyschema.soil =================================================================== diff -u -ra950714ad9510756331d862aa35695fa0b2ed03b -rd514ce187a1ce571355fd92ca1edf822d943ba39 Binary files differ Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/test-data/PipingSoilProfilesReader/invalid2dGeometry.soil =================================================================== diff -u Binary files differ Index: Ringtoets/Piping/test/Ringtoets.Piping.IO.Test/test-data/PipingSoilProfilesReader/invalidbottom.soil =================================================================== diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39 Binary files differ Fisheye: Tag d514ce187a1ce571355fd92ca1edf822d943ba39 refers to a dead (removed) revision in file `Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/PipingSoilProfileImporterTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/PipingSoilProfilesImporterTest.cs =================================================================== diff -u --- Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/PipingSoilProfilesImporterTest.cs (revision 0) +++ Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/FileImporter/PipingSoilProfilesImporterTest.cs (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using Core.Common.BaseDelftTools; +using System.IO; +using Core.Common.TestUtils; +using NUnit.Framework; + +using Rhino.Mocks; + +using Ringtoets.Piping.Data; +using Ringtoets.Piping.Plugin.FileImporter; + +using WtiFormsResources = Ringtoets.Piping.Forms.Properties.Resources; +using ApplicationResources = Ringtoets.Piping.Plugin.Properties.Resources; +using WtiIOResources = Ringtoets.Piping.IO.Properties.Resources; + +namespace Ringtoets.Piping.Plugin.Test.FileImporter +{ + [TestFixture] + public class PipingSoilProfilesImporterTest + { + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Piping.IO, "PipingSoilProfilesReader"); + + [Test] + public void DefaultConstructor_ExpectedValues() + { + // Prepare + var expectedFileFilter = String.Format("{0} {1} (*.soil)|*.soil", + WtiFormsResources.PipingSoilProfilesCollection_DisplayName, ApplicationResources.SoilFileName); + + // Call + var importer = new PipingSoilProfilesImporter(); + + // Assert + Assert.IsInstanceOf(importer); + Assert.AreEqual(WtiFormsResources.PipingSoilProfilesCollection_DisplayName, importer.Name); + Assert.AreEqual(ApplicationResources.WtiApplicationName, importer.Category); + Assert.AreEqual(16, importer.Image.Width); + Assert.AreEqual(16, importer.Image.Height); + CollectionAssert.AreEqual(new[] { typeof(IEnumerable) }, importer.SupportedItemTypes); + Assert.IsFalse(importer.CanImportOnRootLevel); + Assert.AreEqual(expectedFileFilter, importer.FileFilter); + Assert.IsNull(importer.TargetDataDirectory); + Assert.IsFalse(importer.ShouldCancel); + Assert.IsNull(importer.ProgressChanged); + Assert.IsFalse(importer.OpenViewAfterImport); + } + + [Test] + public void CanImportOn_TargetIsCollectionOfPipingSoilProfile_ReturnTrue() + { + // Setup + var mocks = new MockRepository(); + var validTarget = mocks.StrictMock>(); + mocks.ReplayAll(); + + var importer = new PipingSoilProfilesImporter(); + + // Call + var importAllowed = importer.CanImportOn(validTarget); + + // Assert + Assert.IsTrue(importAllowed); + mocks.VerifyAll(); // Expect no calls on mocks. + } + + [Test] + public void CanImportOn_InvalidTarget_ReturnFalse() + { + // Setup + var mocks = new MockRepository(); + var invalidTarget = mocks.StrictMock>(); + mocks.ReplayAll(); + + var importer = new PipingSoilProfilesImporter(); + + // Call + var importAllowed = importer.CanImportOn(invalidTarget); + + // Assert + Assert.IsFalse(importAllowed); + mocks.VerifyAll(); // Expect no calls on mocks. + } + + [Test] + public void ImportItem_ImportingToValidTargetWithValidFile_ImportSoilProfilesToCollection() + { + // Setup + string validFilePath = Path.Combine(testDataPath, "complete.soil"); + var piping = new PipingFailureMechanism(); + + var importer = new PipingSoilProfilesImporter(); + + var importTarget = piping.SoilProfiles; + + // Precondition + Assert.IsTrue(importer.CanImportOn(importTarget)); + + // Call + var importedItem = importer.ImportItem(validFilePath, importTarget); + + // Assert + Assert.AreSame(importTarget, importedItem); + } + + [Test] + public void ImportItem_ImportingToValidTargetWithEmptyFile_AbortImportAndLog() + { + // Setup + string corruptPath = Path.Combine(testDataPath, "empty.soil"); + + var mocks = new MockRepository(); + var observer = mocks.StrictMock(); + mocks.ReplayAll(); + + var importer = new PipingSoilProfilesImporter(); + + var observableSoilProfileList = new ObservableList(); + observableSoilProfileList.Attach(observer); + + object importedItem = null; + + // Call + Action call = () => importedItem = importer.ImportItem(corruptPath, observableSoilProfileList); + + // Assert + var internalErrorMessage = string.Format(WtiIOResources.Error_SoilProfileReadFromDatabase, + Path.GetFileName(corruptPath)); + var expectedLogMessage = string.Format(ApplicationResources.PipingSoilProfilesImporter_CriticalErrorReading_0_Cause_1_, + corruptPath, internalErrorMessage); + TestHelper.AssertLogMessageIsGenerated(call, expectedLogMessage, 1); + Assert.AreSame(observableSoilProfileList, importedItem); + CollectionAssert.IsEmpty(observableSoilProfileList, + "No items should be added to collection when import is aborted."); + mocks.VerifyAll(); // Expect no calls on 'observer' + } + + [Test] + public void ImportItem_ImportingToValidTargetWithProfileContainingInvalidValue_SkipImportAndLog() + { + // Setup + string corruptPath = Path.Combine(testDataPath, "invalid2dGeometry.soil"); + + var mocks = new MockRepository(); + var observer = mocks.StrictMock(); + observer.Expect(o => o.UpdateObserver()); + mocks.ReplayAll(); + + var importer = new PipingSoilProfilesImporter(); + + var observableSoilProfileList = new ObservableList(); + observableSoilProfileList.Attach(observer); + + object importedItem = null; + + // Call + Action call = () => importedItem = importer.ImportItem(corruptPath, observableSoilProfileList); + + // Assert + var internalErrorMessage = string.Format(WtiIOResources.PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_, + 1, "Profile"); + var expectedLogMessage = string.Format(ApplicationResources.PipingSoilProfilesImporter_ReadSoilProfiles_File_0_Message_1_, + corruptPath, internalErrorMessage); + TestHelper.AssertLogMessageIsGenerated(call, expectedLogMessage, 1); + + Assert.AreSame(observableSoilProfileList, importedItem); + Assert.AreEqual(1, observableSoilProfileList.Count); + + mocks.VerifyAll(); + } + } +} \ No newline at end of file Index: Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj =================================================================== diff -u -ra950714ad9510756331d862aa35695fa0b2ed03b -rd514ce187a1ce571355fd92ca1edf822d943ba39 --- Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj (.../Ringtoets.Piping.Plugin.Test.csproj) (revision a950714ad9510756331d862aa35695fa0b2ed03b) +++ Ringtoets/Piping/test/Ringtoets.Piping.Plugin.Test/Ringtoets.Piping.Plugin.Test.csproj (.../Ringtoets.Piping.Plugin.Test.csproj) (revision d514ce187a1ce571355fd92ca1edf822d943ba39) @@ -51,7 +51,7 @@ - +