// 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 2d profile definitions from the Soil database using a constructed reader /// and transform the definitions to a . /// internal static class SoilProfile2DReader { /// /// Reads information for a profile from the database and creates a based on the information. /// /// 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 /// /// a layer's geometry could not be parsed as XML; /// the parsed geometry did not contain loops; /// after reading the layers, no layers were added to be build; /// unexpected values were encountered for layer properties /// /// internal static PipingSoilProfile ReadFrom(IRowBasedDatabaseReader reader) { var criticalProperties = new CriticalProfileProperties(reader); var requiredProperties = new RequiredProfileProperties(reader, criticalProperties.ProfileName); try { var soilProfileBuilder = new SoilProfileBuilder2D(criticalProperties.ProfileName, requiredProperties.IntersectionX, criticalProperties.ProfileId); for (int i = 1; i <= criticalProperties.LayerCount; i++) { var pipingSoilLayer2D = ReadPiping2DSoilLayer(reader, criticalProperties.ProfileName); soilProfileBuilder.Add(pipingSoilLayer2D); reader.MoveNext(); } return soilProfileBuilder.Build(); } catch (SoilProfileBuilderException e) { throw CreatePipingSoilProfileReadException(reader.Path, criticalProperties.ProfileName, e); } catch (ArgumentException e) { throw CreatePipingSoilProfileReadException(reader.Path, criticalProperties.ProfileName, e); } } /// /// Reads a soil layer from a 2d profile in the database. /// /// The to read the layer property values from. /// The profile name used in generating exceptions messages if casting failed. /// A new instance, based on the information read from the database. /// Thrown when: /// /// A column for a layer property did not contain a value of the expected type. /// The database contains an invalid XML definition for geometry. /// The read geometry does not contain segments that form form a loop for either the inner or outer loop. /// private static SoilLayer2D ReadPiping2DSoilLayer(IRowBasedDatabaseReader reader, string profileName) { var properties = new LayerProperties(reader, profileName); SoilLayer2D pipingSoilLayer; try { var geometryValue = ReadGeometryFrom(reader, profileName); pipingSoilLayer = new SoilLayer2DReader().Read(geometryValue); } catch (SoilLayerConversionException e) { throw CreatePipingSoilProfileReadException(reader.Path, profileName, e); } if (pipingSoilLayer != null) { pipingSoilLayer.IsAquifer = properties.IsAquifer; pipingSoilLayer.MaterialName = properties.MaterialName; pipingSoilLayer.Color = properties.Color; pipingSoilLayer.BelowPhreaticLevelDistribution = properties.BelowPhreaticLevelDistribution; pipingSoilLayer.BelowPhreaticLevelShift = properties.BelowPhreaticLevelShift; pipingSoilLayer.BelowPhreaticLevelMean = properties.BelowPhreaticLevelMean; pipingSoilLayer.BelowPhreaticLevelDeviation = properties.BelowPhreaticLevelDeviation; pipingSoilLayer.DiameterD70Distribution = properties.DiameterD70Distribution; pipingSoilLayer.DiameterD70Shift = properties.DiameterD70Shift; pipingSoilLayer.DiameterD70Mean = properties.DiameterD70Mean; pipingSoilLayer.DiameterD70Deviation = properties.DiameterD70Deviation; pipingSoilLayer.PermeabilityDistribution = properties.PermeabilityDistribution; pipingSoilLayer.PermeabilityShift = properties.PermeabilityShift; pipingSoilLayer.PermeabilityMean = properties.PermeabilityMean; pipingSoilLayer.PermeabilityDeviation = properties.PermeabilityDeviation; } return pipingSoilLayer; } /// /// Reads the geometry for a layer from the current /// /// The to read the geometry value from. /// The profile name used in generating exceptions messages if casting failed. /// private static byte[] ReadGeometryFrom(IRowBasedDatabaseReader reader, string profileName) { try { return reader.Read(SoilProfileDatabaseColumns.LayerGeometry); } catch (InvalidCastException e) { throw CreatePipingSoilProfileReadException(reader.Path, profileName, e); } } 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 RequiredProfileProperties { internal readonly double IntersectionX; /// /// 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.IntersectionX; try { IntersectionX = 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); } } } } }