// Copyright (C) Stichting Deltares 2017. 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;
using System.Data.SQLite;
using Core.Common.Base.IO;
using Core.Common.IO.Readers;
using Core.Common.Utils.Builders;
using Ringtoets.MacroStabilityInwards.Data.SoilProfile;
using Ringtoets.MacroStabilityInwards.IO.Builders;
using Ringtoets.MacroStabilityInwards.IO.Exceptions;
using Ringtoets.MacroStabilityInwards.IO.Properties;
using Ringtoets.MacroStabilityInwards.IO.SoilProfile.Schema;
using Ringtoets.MacroStabilityInwards.Primitives;
namespace Ringtoets.MacroStabilityInwards.IO.SoilProfile
{
///
/// This class reads a D-Soil Model file and reads
/// from this database.
///
public class StochasticSoilProfileReader : SqLiteDatabaseReaderBase
{
private IDataReader dataReader;
///
/// Creates a new instance of ,
/// which will use the as its source.
///
/// The path of the database file to open.
/// Thrown when:
/// - The contains invalid characters.
/// - No file could be found at .
/// - The database version could not be read.
/// - The database version is incorrect.
///
public StochasticSoilProfileReader(string databaseFilePath) : base(databaseFilePath)
{
VerifyVersion(databaseFilePath);
InitializeReader();
}
///
/// Gets a value indicating whether or not more stochastic soil profiles can be read
/// using the .
///
public bool HasNext { get; private set; }
///
/// Reads the information for the next stochastic soil profile from the database
/// and creates a instance of the information.
///
/// Identifier of the next
/// to look for.
/// The next from the database, or null
/// if no more stochastic soil profiles can be read.
/// Thrown when the database returned
/// incorrect values for required properties.
/// Rows are being read in ascending order based on the database ID of the
/// stochastic soil model. Therefore once a stochastic soil model has been read already,
/// it will not be found with this method.
public MacroStabilityInwardsStochasticSoilProfile ReadStochasticSoilProfile(long stochasticSoilModelId)
{
if (!HasNext)
{
return null;
}
if (!MoveToStochasticSoilModelId(stochasticSoilModelId))
{
return null;
}
try
{
MacroStabilityInwardsStochasticSoilProfile stochasticSoilProfile = ReadStochasticSoilProfileProbability();
MoveToNextStochasticSoilModelId(stochasticSoilModelId);
return stochasticSoilProfile;
}
catch (SystemException exception)
{
if (exception is FormatException || exception is OverflowException || exception is InvalidCastException)
{
string message = new FileReaderErrorMessageBuilder(Path)
.Build(Resources.StochasticSoilProfileDatabaseReader_StochasticSoilProfile_has_invalid_value);
throw new StochasticSoilProfileReadException(message, exception);
}
throw;
}
}
protected override void Dispose(bool disposing)
{
dataReader?.Dispose();
base.Dispose(disposing);
}
///
/// Prepares a new data reader with queries for obtaining the profiles and updates
/// the reader so that it points to the first row of the result set.
///
/// A query could not be executed on
/// the database schema.
private void InitializeReader()
{
CreateDataReader();
MoveNext();
}
///
/// Moves the reader to the next record in the database.
///
private void MoveNext()
{
HasNext = MoveNext(dataReader);
}
private void CreateDataReader()
{
string stochasticSoilProfileQuery = SoilDatabaseQueryBuilder.GetAllStochasticSoilProfileQuery();
try
{
dataReader = CreateDataReader(stochasticSoilProfileQuery);
}
catch (SQLiteException exception)
{
CloseConnection();
string message = new FileReaderErrorMessageBuilder(Path)
.Build(Resources.StochasticSoilModelDatabaseReader_Failed_to_read_database);
throw new CriticalFileReadException(message, exception);
}
}
private bool MoveToStochasticSoilModelId(long stochasticSoilModelId)
{
while (HasNext && ReadStochasticSoilModelId() < stochasticSoilModelId)
{
MoveNext();
}
if (HasNext && ReadStochasticSoilModelId() == stochasticSoilModelId)
{
return true;
}
MoveToNextStochasticSoilModelId(stochasticSoilModelId);
return false;
}
private void MoveToNextStochasticSoilModelId(long stochasticSoilModelId)
{
MoveNext();
if (HasNext)
{
HasNext = ReadStochasticSoilModelId() == stochasticSoilModelId;
}
}
private void VerifyVersion(string databaseFilePath)
{
using (var versionReader = new SoilDatabaseVersionReader(databaseFilePath))
{
try
{
versionReader.VerifyVersion();
}
catch (CriticalFileReadException)
{
CloseConnection();
throw;
}
}
}
private long ReadStochasticSoilModelId()
{
return Convert.ToInt64(dataReader[StochasticSoilProfileTableColumns.StochasticSoilModelId]);
}
private MacroStabilityInwardsStochasticSoilProfile ReadStochasticSoilProfileProbability()
{
object valueProbability = dataReader[StochasticSoilProfileTableColumns.Probability];
double probability = valueProbability.Equals(DBNull.Value) ? 0 : Convert.ToDouble(valueProbability);
MacroStabilityInwardsStochasticSoilProfile soilProfile1DId = ReadSoilProfile1DId(probability);
if (soilProfile1DId != null)
{
return soilProfile1DId;
}
MacroStabilityInwardsStochasticSoilProfile soilProfile2DId = ReadSoilProfile2DId(probability);
if (soilProfile2DId != null)
{
return soilProfile2DId;
}
string message = new FileReaderErrorMessageBuilder(Path)
.Build(Resources.StochasticSoilProfileDatabaseReader_StochasticSoilProfile_has_invalid_value);
throw new StochasticSoilProfileReadException(message);
}
private MacroStabilityInwardsStochasticSoilProfile ReadSoilProfile2DId(double probability)
{
object valueSoilProfile2DId = dataReader[StochasticSoilProfileTableColumns.SoilProfile2DId];
if (!valueSoilProfile2DId.Equals(DBNull.Value))
{
long soilProfileId = Convert.ToInt64(valueSoilProfile2DId);
return new MacroStabilityInwardsStochasticSoilProfile(probability, SoilProfileType.SoilProfile2D, soilProfileId);
}
return null;
}
private MacroStabilityInwardsStochasticSoilProfile ReadSoilProfile1DId(double probability)
{
object valueSoilProfile1DId = dataReader[StochasticSoilProfileTableColumns.SoilProfile1DId];
if (!valueSoilProfile1DId.Equals(DBNull.Value))
{
long soilProfileId = Convert.ToInt64(valueSoilProfile1DId);
return new MacroStabilityInwardsStochasticSoilProfile(probability, SoilProfileType.SoilProfile1D, soilProfileId);
}
return null;
}
}
}