// 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);
}
}
}
}
}