Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs
===================================================================
diff -u -ra483049c20ef6d26addd0718d0f31ae1922e6f49 -rd514ce187a1ce571355fd92ca1edf822d943ba39
--- Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision a483049c20ef6d26addd0718d0f31ae1922e6f49)
+++ Ringtoets/Piping/src/Ringtoets.Piping.IO/PipingSoilProfileReader.cs (.../PipingSoilProfileReader.cs) (revision d514ce187a1ce571355fd92ca1edf822d943ba39)
@@ -12,7 +12,6 @@
{
///
/// This class reads a SqLite database file and constructs from this database.
- /// The database is created with the DSoilModel application.
///
public class PipingSoilProfileReader : IDisposable
{
@@ -37,64 +36,53 @@
private SQLiteConnection connection;
private SQLiteDataReader dataReader;
+ private readonly string databaseFileName;
+ private readonly string databaseRequiredVersion = "15.0.5.0";
+
///
- /// Creates a new instance of which will use the
- /// as its source. The reader will not point to any record at the start. Use to start reading
+ /// Creates a new instance of which will use the
+ /// as its source. The reader will not point to any record at the start. Use to start reading
/// profiles.
///
- /// The path of the database file to open.
- public PipingSoilProfileReader(string dbFile)
+ /// The path of the database file to open.
+ public PipingSoilProfileReader(string databaseFilePath)
{
- if (String.IsNullOrEmpty(dbFile))
+ if (String.IsNullOrEmpty(databaseFilePath))
{
throw new ArgumentException(Resources.Error_PathMustBeSpecified);
}
- if (!File.Exists(dbFile))
+ if (!File.Exists(databaseFilePath))
{
- throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, dbFile));
+ throw new FileNotFoundException(String.Format(Resources.Error_File_0_does_not_exist, databaseFilePath));
}
- OpenConnection(dbFile);
+ databaseFileName = Path.GetFileName(databaseFilePath);
+ OpenConnection(databaseFilePath);
+ SetReaderToFirstRecord();
}
///
+ /// Gets the value true if profiles can be read using the .
+ /// false otherwise.
+ ///
+ public bool HasNext { get; private set; }
+
+ ///
/// Prepares the next layer from the database.
///
/// False if there are no more rows to be read. True otherwise.
- /// Thrown when reading the layer entry from the database failed.
/// Thrown when parsing the geometry of a 2d soil layer failed.
public PipingSoilProfile ReadProfile()
{
- if (dataReader == null)
+ if (!HasNext)
{
- throw new InvalidOperationException(GetType() + " was not initialized using Next()");
+ throw new InvalidOperationException("Reader has reached the end and cannot read more profiles.");
}
- return TryRead(dimensionColumn) == 1 ? ReadPipingProfile1D().Build() : ReadPipingProfile2D().Build();
+ var dimensionValue = Read(dimensionColumn);
+ return dimensionValue == 1 ? ReadPipingProfile1D().Build() : ReadPipingProfile2D().Build();
}
- ///
- /// Moves the reader to the next record in the database.
- ///
- /// true if there was another record. Otherwise, false.
- /// You should never make two calls to this method without calling in between.
- public bool Next()
- {
- InitializeReader();
- if (!dataReader.Read())
- {
- if (dataReader.NextResult())
- {
- return dataReader.Read();
- }
- }
- else
- {
- return true;
- }
- return false;
- }
-
public void Dispose()
{
if (dataReader != null)
@@ -105,64 +93,90 @@
connection.Dispose();
}
+ ///
+ /// Moves the reader to the next record in the database.
+ ///
+ private void MoveNext()
+ {
+ HasNext = dataReader.Read() || (dataReader.NextResult() && dataReader.Read());
+ }
+
private ISoilProfileBuilder ReadPipingProfile1D()
{
- var profileName = TryRead(profileNameColumn);
- var bottom = TryRead(bottomColumn);
- var layerCount = TryRead(layerCountColumn);
+ var profileName = Read(profileNameColumn);
+ var layerCount = Read(layerCountColumn);
+ var bottom = Read(bottomColumn);
+
var soilProfileBuilder = new SoilProfileBuilder1D(profileName, bottom);
- for (int i = 1; i <= layerCount; i++)
+ for (var i = 1; i <= layerCount; i++)
{
soilProfileBuilder.Add(ReadPipingSoilLayer());
- if (i < layerCount)
- {
- Next();
- }
+ MoveNext();
}
+
return soilProfileBuilder;
}
private ISoilProfileBuilder ReadPipingProfile2D()
{
- var profileName = TryRead(profileNameColumn);
- var intersectionX = TryRead(intersectionXColumn);
- var layerCount = TryRead(layerCountColumn);
+ var profileName = Read(profileNameColumn);
+ var layerCount = Read(layerCountColumn);
+ var intersectionX = Read(intersectionXColumn);
+
var soilProfileBuilder = new SoilProfileBuilder2D(profileName, intersectionX);
for (int i = 1; i <= layerCount; i++)
{
- soilProfileBuilder.Add(ReadPiping2DSoilLayer());
- if (i < layerCount)
+ try
{
- Next();
+ soilProfileBuilder.Add(ReadPiping2DSoilLayer());
}
+ catch (XmlException e)
+ {
+ var exception = new PipingSoilProfileReadException(
+ string.Format(Resources.PipingSoilProfileReader_CouldNotParseGeometryOfLayer_0_InProfile_1_, i, profileName), e);
+
+ while (i++ <= layerCount)
+ {
+ MoveNext();
+ }
+
+ throw exception;
+ }
+ MoveNext();
}
+
return soilProfileBuilder;
}
- private void InitializeReader()
+ private void SetReaderToFirstRecord()
{
- if (dataReader == null)
- {
- PrepareQueries();
- }
+ InitializeDataReader();
+ MoveNext();
}
- private T TryRead(string columnName)
+ private bool TryRead(string columnName, out T value)
{
try
{
- return (T) dataReader[columnName];
+ value = (T) dataReader[columnName];
+ return true;
}
catch (InvalidCastException e)
{
- throw new PipingSoilProfileReadException(String.Format(Resources.PipingSoilProfileReader_InvalidValueOnColumn, columnName), e);
+ value = default(T);
+ return false;
}
}
+ private T Read(string columnName)
+ {
+ return (T)dataReader[columnName];
+ }
+
private void OpenConnection(string dbFile)
{
var connectionStringBuilder = new SQLiteConnectionStringBuilder
@@ -191,28 +205,55 @@
private PipingSoilLayer ReadPipingSoilLayer()
{
- var columnValue = TryRead(topColumn);
- var isAquiferValue = TryRead(isAquiferColumn);
- var pipingSoilLayer = new PipingSoilLayer(columnValue)
+ double topValue;
+ double isAquiferValue;
+
+ var columnValueRead = TryRead(topColumn, out topValue);
+ var isAquiferValueRead = TryRead(isAquiferColumn, out isAquiferValue);
+
+ if (!columnValueRead || !isAquiferValueRead)
{
+ return null;
+ }
+
+ var pipingSoilLayer = new PipingSoilLayer(topValue)
+ {
IsAquifer = isAquiferValue.Equals(1.0)
};
return pipingSoilLayer;
}
private SoilLayer2D ReadPiping2DSoilLayer()
{
- var geometry = TryRead(layerGeometryColumn);
- var isAquiferValue = TryRead(isAquiferColumn);
+ double isAquiferValue;
+ byte[] geometryValue;
- SoilLayer2D pipingSoilLayer = new PipingSoilLayer2DReader(geometry).Read();
+ var geometryRead = TryRead(layerGeometryColumn, out geometryValue);
+ var isAquiferValueRead = TryRead(isAquiferColumn, out isAquiferValue);
+
+ if (!geometryRead || !isAquiferValueRead)
+ {
+ return null;
+ }
+
+ SoilLayer2D pipingSoilLayer = new PipingSoilLayer2DReader(geometryValue).Read();
pipingSoilLayer.IsAquifer = isAquiferValue.Equals(1.0);
return pipingSoilLayer;
}
- private void PrepareQueries()
+ ///
+ /// Prepares the two queries required for obtaining all the SoilProfile1D and SoilProfile2D with an x defined
+ /// to take an intersection from. Since two separate queries are used, the will
+ /// have two result sets which the method takes into account.
+ ///
+ private void InitializeDataReader()
{
+ string versionQuery = string.Format(
+ "SELECT Value FROM _Metadata WHERE Key = 'VERSION' AND Value = '{0}';",
+ databaseRequiredVersion
+ );
+
string materialPropertiesQuery = string.Format(
string.Join(" ",
"(SELECT",
@@ -343,7 +384,7 @@
layer2DPropertiesQuery,
mechanismParameterName);
- dataReader = CreateDataReader(query2D + query1D, new SQLiteParameter
+ CreateDataReader(versionQuery + query2D + query1D, new SQLiteParameter
{
DbType = DbType.String,
Value = pipingMechanismName,
@@ -352,9 +393,9 @@
}
///
- /// Creates a new data reader to use in this class, based on a query which returns all the known soil layers for which its profile has a X coordinate defined for piping.
+ /// Creates a new data reader to use in this class.
///
- private SQLiteDataReader CreateDataReader(string queryString, params SQLiteParameter[] parameters)
+ private void CreateDataReader(string queryString, params SQLiteParameter[] parameters)
{
using (var query = new SQLiteCommand(connection)
{
@@ -365,13 +406,27 @@
try
{
- return query.ExecuteReader();
+ dataReader = query.ExecuteReader();
+ CheckVersion();
}
catch (SQLiteException e)
{
- throw new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, connection.DataSource), e);
+ connection.Dispose();
+ var exception = new PipingSoilProfileReadException(string.Format(Resources.Error_SoilProfileReadFromDatabase, databaseFileName), e);
+ throw exception;
}
}
}
+
+ private void CheckVersion()
+ {
+ if (!dataReader.HasRows)
+ {
+ throw new PipingSoilProfileReadException(String.Format(
+ Resources.PipingSoilProfileReader_DatabaseFileIncorrectVersions_Requires_0,
+ databaseRequiredVersion));
+ }
+ dataReader.NextResult();
+ }
}
}
\ No newline at end of file