// 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.Exceptions; 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 encountering an unrecoverable error while reading the profile. /// Thrown when encountering an recoverable error while reading the profile 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); try { 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); } catch (SoilLayerConversionException e) { throw CreatePipingSoilProfileReadException(reader.Path, profileName, e); } } /// /// Builds a from the given . /// /// Thrown when building the fails. 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 Layer1DProperties(reader, profileName); var pipingSoilLayer = new SoilLayer1D(properties.Top) { IsAquifer = properties.IsAquifer, MaterialName = properties.MaterialName, Color = properties.Color, BelowPhreaticLevelDistribution = properties.BelowPhreaticLevelDistribution, BelowPhreaticLevelShift = properties.BelowPhreaticLevelShift, BelowPhreaticLevelMean = properties.BelowPhreaticLevelMean, BelowPhreaticLevelDeviation = properties.BelowPhreaticLevelDeviation, DiameterD70Distribution = properties.DiameterD70Distribution, DiameterD70Shift = properties.DiameterD70Shift, DiameterD70Mean = properties.DiameterD70Mean, DiameterD70Deviation = properties.DiameterD70Deviation, PermeabilityDistribution = properties.PermeabilityDistribution, PermeabilityShift = properties.PermeabilityShift, PermeabilityMean = properties.PermeabilityMean, PermeabilityDeviation = properties.PermeabilityDeviation }; return pipingSoilLayer; } private static PipingSoilProfileReadException CreatePipingSoilProfileReadException(string filePath, string profileName, string errorMessage, Exception innerException) { var message = new FileReaderErrorMessageBuilder(filePath) .WithSubject(string.Format(Resources.PipingSoilProfileReader_SoilProfileName_0_, profileName)) .Build(errorMessage); return new PipingSoilProfileReadException(profileName, message, innerException); } private static PipingSoilProfileReadException CreatePipingSoilProfileReadException(string filePath, string profileName, Exception innerException) { var message = new FileReaderErrorMessageBuilder(filePath) .WithSubject(string.Format(Resources.PipingSoilProfileReader_SoilProfileName_0_, profileName)) .Build(innerException.Message); return new PipingSoilProfileReadException(profileName, message, innerException); } private class Layer1DProperties : LayerProperties { /// /// 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 Layer1DProperties(IRowBasedDatabaseReader reader, string profileName) : base(reader, profileName) { string readColumn = SoilProfileDatabaseColumns.Top; try { Top = reader.Read(readColumn); } catch (InvalidCastException e) { var message = string.Format(Resources.PipingSoilProfileReader_Profile_has_invalid_value_on_Column_0_, readColumn); throw CreatePipingSoilProfileReadException(reader.Path, profileName, message, e); } } /// /// Gets the top level of the 1D soil layer. /// internal double Top { get; private set; } } 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); } } } } }