// 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.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Linq;
using Core.Common.Base.Geometry;
using Core.Common.Base.IO;
using Core.Common.IO.Readers;
using Core.Common.Util.Builders;
using Ringtoets.Common.IO.Exceptions;
using Ringtoets.Common.IO.Properties;
using Ringtoets.Common.IO.SoilProfile.Schema;
namespace Ringtoets.Common.IO.SoilProfile
{
///
/// This class reads a D-Soil Model file and reads segment points from this database.
///
public class SegmentPointReader : 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 .
///
///
public SegmentPointReader(string databaseFilePath) : base(databaseFilePath) {}
///
/// Gets a value indicating whether or not more stochastic soil model geometry can be
/// read using the .
///
public bool HasNext { get; private set; }
///
/// Initializes the database.
///
/// Thrown when the query to fetch stochastic
/// soil model segment points from the database failed.
public void Initialize()
{
CreateDataReader();
MoveNext();
}
///
/// Reads the segment points corresponding to the stochastic soil model.
///
/// The segment points corresponding to the stochastic soil model.
/// Thrown when the geometry could not be read.
public IEnumerable ReadSegmentPoints()
{
return !HasNext
? Enumerable.Empty()
: TryReadSegmentPoints();
}
///
/// Reads the stochastic soil model id from the data reader.
///
/// The stochastic soil model id.
/// Thrown when the data reader does not point to a row.
public long ReadStochasticSoilModelId()
{
if (!HasNext)
{
throw new InvalidOperationException("The reader does not have a row to read.");
}
return Convert.ToInt64(dataReader[StochasticSoilModelTableDefinitions.StochasticSoilModelId]);
}
protected override void Dispose(bool disposing)
{
if (dataReader != null)
{
dataReader.Close();
dataReader.Dispose();
dataReader = null;
}
base.Dispose(disposing);
}
///
/// Tries to read the segment points corresponding to the stochastic soil model.
///
/// The segment points corresponding to the stochastic soil model.
/// Thrown when the geometry could not be read.
private IEnumerable TryReadSegmentPoints()
{
var segmentPoints = new List();
long currentStochasticSoilModelId = ReadStochasticSoilModelId();
try
{
while (HasNext && ReadStochasticSoilModelId() == currentStochasticSoilModelId)
{
segmentPoints.Add(ReadSegmentPoint());
MoveNext();
}
}
catch (StochasticSoilModelException)
{
MoveToNextStochasticSoilModel();
throw;
}
return segmentPoints;
}
///
/// Moves the reader to the next stochastic soil model.
///
private void MoveToNextStochasticSoilModel()
{
long currentStochasticSoilModelId = ReadStochasticSoilModelId();
while (HasNext && currentStochasticSoilModelId.Equals(ReadStochasticSoilModelId()))
{
MoveNext();
}
}
private string ReadStochasticSoilModelSegmentName()
{
return Convert.ToString(dataReader[StochasticSoilModelTableDefinitions.StochasticSoilModelName]);
}
///
/// Reads the segment point from the database.
///
/// The segment point.
/// Thrown when the geometry could not be read.
private Point2D ReadSegmentPoint()
{
object coordinateX = dataReader[SegmentPointsTableDefinitions.CoordinateX];
object coordinateY = dataReader[SegmentPointsTableDefinitions.CoordinateY];
if (coordinateX == Convert.DBNull || coordinateY == Convert.DBNull)
{
throw new StochasticSoilModelException(
string.Format(Resources.SegmentPointReader_ReadSegmentPoint_StochasticSoilModel_0_must_contain_geometry,
ReadStochasticSoilModelSegmentName()));
}
double coordinateXValue = Convert.ToDouble(coordinateX);
double coordinateYValue = Convert.ToDouble(coordinateY);
return new Point2D(coordinateXValue, coordinateYValue);
}
///
/// Creates a new .
///
/// Thrown when the query to fetch stochastic soil
/// model segment points from the database failed.
private void CreateDataReader()
{
string stochasticSoilModelSegmentsQuery = SoilDatabaseQueryBuilder.GetSegmentPointsQuery();
try
{
dataReader = CreateDataReader(stochasticSoilModelSegmentsQuery);
}
catch (SQLiteException exception)
{
string message = new FileReaderErrorMessageBuilder(Path).Build(Resources.StochasticSoilModelDatabaseReader_Failed_to_read_database);
throw new CriticalFileReadException(message, exception);
}
}
private void MoveNext()
{
HasNext = MoveNext(dataReader);
}
}
}