// Copyright (C) Stichting Deltares 2016. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets 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.Data.SQLite; using Core.Common.IO.Readers; using Core.Common.Utils.Builders; using Ringtoets.Piping.IO.Builders; using Ringtoets.Piping.IO.Exceptions; using Ringtoets.Piping.IO.Properties; using Ringtoets.Piping.Primitives; namespace Ringtoets.Piping.IO.SoilProfile { /// /// This class is responsible for reading 1d profile definitions from the Soil database using a constructed reader /// and transform the definitions to a . /// internal static class SoilProfile1DReader { /// /// Reads a 1D profile from the given . /// /// A which is used to read row values from. /// A new , which is based on the information from the database. /// Thrown when reading the profile encountered an unrecoverable error. /// Thrown when reading the profile encountered a recoverable error. internal static PipingSoilProfile ReadFrom(IRowBasedDatabaseReader reader) { var criticalProperties = new CriticalProfileProperties(reader); var profileId = criticalProperties.ProfileId; var profileName = criticalProperties.ProfileName; var requiredProperties = new RequiredProfileProperties(reader, profileName); var soilProfileBuilder = new SoilProfileBuilder1D(profileName, requiredProperties.Bottom, profileId); for (var i = 1; i <= criticalProperties.LayerCount; i++) { SoilLayer1D soilLayer = ReadSoilLayerFrom(reader, profileName); soilProfileBuilder.Add(soilLayer.AsPipingSoilLayer()); reader.MoveNext(); } return Build(soilProfileBuilder, reader.Path, profileName); } /// /// Builds a from the given . /// /// Thrown when building the failed. private static PipingSoilProfile Build(SoilProfileBuilder1D soilProfileBuilder, string path, string profileName) { try { return soilProfileBuilder.Build(); } catch (SoilProfileBuilderException e) { var message = new FileReaderErrorMessageBuilder(path) .WithSubject(string.Format(Resources.PipingSoilProfileReader_SoilProfileName_0_, profileName)) .Build(e.Message); throw new PipingSoilProfileReadException(profileName, message, e); } } /// /// Reads a from the given . /// /// Thrown when reading properties of the layers failed. private static SoilLayer1D ReadSoilLayerFrom(IRowBasedDatabaseReader reader, string profileName) { var properties = new LayerProperties(reader, profileName); var pipingSoilLayer = new SoilLayer1D(properties.Top) { IsAquifer = properties.IsAquifer, BelowPhreaticLevel = properties.BelowPhreaticLevel, AbovePhreaticLevel = properties.AbovePhreaticLevel, DryUnitWeight = properties.DryUnitWeight, MaterialName = properties.MaterialName, Color = properties.Color }; return pipingSoilLayer; } private class LayerProperties { internal readonly double Top; internal readonly double? IsAquifer; internal readonly double? BelowPhreaticLevel; internal readonly double? AbovePhreaticLevel; internal readonly double? DryUnitWeight; internal readonly string MaterialName; internal readonly double? Color; /// /// Creates a new instance of , which contains properties /// that are required to create a complete . If these properties /// cannot be read, then the reader can proceed to the next profile. /// /// The to read the required layer property values from. /// The profile name used in generating exceptions messages if casting failed. /// Thrown when the values in the database could not be /// casted to the expected column types. internal LayerProperties(IRowBasedDatabaseReader reader, string profileName) { string readColumn = SoilProfileDatabaseColumns.Top; try { Top = reader.Read(readColumn); readColumn = SoilProfileDatabaseColumns.IsAquifer; IsAquifer = reader.ReadOrDefault(readColumn); readColumn = SoilProfileDatabaseColumns.BelowPhreaticLevel; BelowPhreaticLevel = reader.ReadOrDefault(readColumn); readColumn = SoilProfileDatabaseColumns.AbovePhreaticLevel; AbovePhreaticLevel = reader.ReadOrDefault(readColumn); readColumn = SoilProfileDatabaseColumns.DryUnitWeight; DryUnitWeight = reader.ReadOrDefault(readColumn); readColumn = SoilProfileDatabaseColumns.MaterialName; MaterialName = reader.ReadOrDefault(readColumn); readColumn = SoilProfileDatabaseColumns.Color; Color = reader.ReadOrDefault(readColumn); } catch (InvalidCastException e) { var message = new FileReaderErrorMessageBuilder(reader.Path) .WithSubject(String.Format(Resources.PipingSoilProfileReader_SoilProfileName_0_, profileName)) .Build(string.Format(Resources.PipingSoilProfileReader_Profile_has_invalid_value_on_Column_0_, readColumn)); throw new PipingSoilProfileReadException(profileName, message, e); } } } private class RequiredProfileProperties { internal readonly double Bottom; /// /// Creates a new instance of , which contains properties /// that are required to create a complete . If these properties /// cannot be read, then the reader can proceed to the next profile. /// /// The to read the required profile property values from. /// The profile name used in generating exceptions messages if casting failed. /// Thrown when the values in the database could not be /// casted to the expected column types. internal RequiredProfileProperties(IRowBasedDatabaseReader reader, string profileName) { string readColumn = SoilProfileDatabaseColumns.Bottom; try { Bottom = reader.Read(readColumn); } catch (InvalidCastException e) { var message = new FileReaderErrorMessageBuilder(reader.Path) .WithSubject(string.Format(Resources.PipingSoilProfileReader_SoilProfileName_0_, profileName)) .Build(string.Format(Resources.PipingSoilProfileReader_Profile_has_invalid_value_on_Column_0_, readColumn)); throw new PipingSoilProfileReadException(profileName, message, e); } } } } }