// 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;
using System.Data.SQLite;
using Core.Common.IO.Exceptions;
using Core.Common.IO.Readers;
using Core.Common.Utils.Builders;
using Ringtoets.HydraRing.Data;
using Ringtoets.HydraRing.IO.Properties;
namespace Ringtoets.HydraRing.IO.HydraulicBoundaryDatabaseContext
{
///
/// This class reads a SqLite database file and constructs
/// instances from this database.
///
public class HydraulicBoundarySqLiteDatabaseReader : SqLiteDatabaseReaderBase
{
private SQLiteDataReader sqliteDataReader;
///
/// 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 HydraulicBoundarySqLiteDatabaseReader(string databaseFilePath) : base(databaseFilePath) {}
///
/// Gets a value indicating whether or not more hydraulic boundary locations can
/// be read using the .
///
public bool HasNext { get; private set; }
///
/// Reads the next location from the database.
///
/// New instance of , based on the
/// data read from the database or null if no data is available.
/// Thrown when the database returned incorrect
/// values for required properties.
public void PrepareReadLocation()
{
CloseDataReader();
HasNext = false;
string locationsQuery = HydraulicBoundaryDatabaseQueryBuilder.GetRelevantLocationsQuery();
sqliteDataReader = CreateDataReader(locationsQuery, new SQLiteParameter
{
DbType = DbType.String
});
MoveNext();
}
public HrdLocation ReadLocation()
{
if (!HasNext)
{
return null;
}
try
{
return ReadHrdLocation();
}
catch (InvalidCastException e)
{
var message = new FileReaderErrorMessageBuilder(Path).
Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column);
throw new LineParseException(message, e);
}
}
///
/// Gets the database version from the metadata table.
///
/// The version found in the database, or if the version
/// cannot be found.
/// Thrown when a query could not be executed on the database schema.
public string GetVersion()
{
string versionQuery = HydraulicBoundaryDatabaseQueryBuilder.GetVersionQuery();
try
{
using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, null))
{
return !dataReader.Read() ? String.Empty : Convert.ToString(dataReader[GeneralTableDefinitions.GeneratedVersion]);
}
}
catch (SQLiteException exception)
{
var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database);
throw new CriticalFileReadException(message, exception);
}
}
///
/// Gets the region id from the metadata table.
///
/// The region id found in the database, or 0 if the region id
/// cannot be found.
/// Thrown when the database returned incorrect
/// values for required properties.
/// Thrown when a query could not be executed on the database schema.
public long GetRegionId()
{
string versionQuery = HydraulicBoundaryDatabaseQueryBuilder.GetRegionIdQuery();
var sqliteParameter = new SQLiteParameter
{
DbType = DbType.String
};
try
{
using (SQLiteDataReader dataReader = CreateDataReader(versionQuery, sqliteParameter))
{
return !dataReader.Read() ? 0 : Convert.ToInt64(dataReader[GeneralTableDefinitions.RegionId]);
}
}
catch (InvalidCastException exception)
{
var message = new FileReaderErrorMessageBuilder(Path).
Build(Resources.HydraulicBoundaryDatabaseReader_Critical_Unexpected_value_on_column);
throw new LineParseException(message, exception);
}
catch (SQLiteException exception)
{
var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database);
throw new CriticalFileReadException(message, exception);
}
}
///
/// Gets the amount of locations that can be read from the database.
///
/// The amount of locations that can be read.
/// Thrown when a query could not be executed on the database schema.
public int GetLocationCount()
{
string locationCountQuery = HydraulicBoundaryDatabaseQueryBuilder.GetRelevantLocationsCountQuery();
var sqliteParameter = new SQLiteParameter
{
DbType = DbType.String
};
try
{
using (SQLiteDataReader dataReader = CreateDataReader(locationCountQuery, sqliteParameter))
{
return !dataReader.Read() ? 0 : Convert.ToInt32(dataReader[HrdLocationsTableDefinitions.Count]);
}
}
catch (InvalidCastException)
{
return 0;
}
catch (SQLiteException exception)
{
var message = new FileReaderErrorMessageBuilder(Path).Build(Resources.Error_HydraulicBoundaryLocation_read_from_database);
throw new CriticalFileReadException(message, exception);
}
}
public override void Dispose()
{
CloseDataReader();
base.Dispose();
}
///
/// Moves the reader to the next record in the database.
///
private void MoveNext()
{
HasNext = MoveNext(sqliteDataReader);
}
///
/// Reads a value at column from the database.
///
/// The expected type of value in the column with name .
/// The name of the column to read from.
/// The read value from the column with name .
/// Thrown when the value in the column was not of type
/// .
private T Read(string columnName)
{
return (T) sqliteDataReader[columnName];
}
///
/// Reads the current row into a new instance of .
///
/// A new instance of , based upon the current row.
/// Thrown when the database returned incorrect values for
/// required properties.
private HrdLocation ReadHrdLocation()
{
try
{
var id = Read(HrdLocationsTableDefinitions.HrdLocationId);
var name = Read(HrdLocationsTableDefinitions.Name);
var x = Read(HrdLocationsTableDefinitions.XCoordinate);
var y = Read(HrdLocationsTableDefinitions.YCoordinate);
MoveNext();
return new HrdLocation(id, name, x, y);
}
catch (InvalidCastException)
{
MoveNext();
throw;
}
}
private void CloseDataReader()
{
if (sqliteDataReader != null)
{
sqliteDataReader.Dispose();
}
}
}
}