Index: src/Plugins/Wti/Wti.IO/PipingSurfaceLinesCsvReader.cs
===================================================================
diff -u -r91ec76d4b8a0fcf5962f442021c43f1ffa70743e -raa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9
--- src/Plugins/Wti/Wti.IO/PipingSurfaceLinesCsvReader.cs (.../PipingSurfaceLinesCsvReader.cs) (revision 91ec76d4b8a0fcf5962f442021c43f1ffa70743e)
+++ src/Plugins/Wti/Wti.IO/PipingSurfaceLinesCsvReader.cs (.../PipingSurfaceLinesCsvReader.cs) (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -71,7 +72,7 @@
{
using (var reader = InitializeStreamReader(filePath))
{
- ValidateHeader(reader);
+ ValidateHeader(reader, 1);
return CountNonEmptyLines(reader, 2);
}
@@ -94,8 +95,11 @@
///
/// A parse error has occurred for the current row, which may be caused by:
///
+ /// - The row doesn't contain any supported separator character.
/// - The row contains a coordinate value that cannot be parsed as a double.
/// - The row contains a number that is too big or too small to be represented with a double.
+ /// - The row is missing an identifier value.
+ /// - The row is missing values to form a surface line point.
///
///
public PipingSurfaceLine ReadLine()
@@ -104,41 +108,116 @@
{
fileReader = InitializeStreamReader(filePath);
- ValidateHeader(fileReader);
+ ValidateHeader(fileReader, 1);
lineNumber = 2;
}
- var readText = ReadLineAndHandleIOExceptions(fileReader);
+ var readText = ReadLineAndHandleIOExceptions(fileReader, lineNumber);
if (readText != null)
{
- var tokenizedString = readText.Split(separator);
- var worldCoordinateValues = ParseWorldCoordinateValuesAndHandleParseErrors(tokenizedString);
-
- // TODO: Format Error: missing values to complete coordinate triplet
- int coordinateCount = worldCoordinateValues.Length / 3;
- var points = new Point3D[coordinateCount];
- for (int i = 0; i < coordinateCount; i++)
+ try
{
- points[i] = new Point3D
+ var tokenizedString = TokenizeString(readText);
+
+ var surfaceLineName = GetSurfaceLineName(tokenizedString);
+ var points = GetSurfaceLinePoints(tokenizedString);
+
+ var surfaceLine = new PipingSurfaceLine
{
- X = worldCoordinateValues[i * 3],
- Y = worldCoordinateValues[i * 3 + 1],
- Z = worldCoordinateValues[i * 3 + 2]
+ Name = surfaceLineName
};
+ surfaceLine.SetGeometry(points);
+ return surfaceLine;
}
+ finally
+ {
+ lineNumber++;
+ }
+ }
- lineNumber++;
+ return null;
+ }
- var surfaceLine = new PipingSurfaceLine
+ public void Dispose()
+ {
+ if (fileReader != null)
+ {
+ fileReader.Dispose();
+ fileReader = null;
+ }
+ }
+
+ ///
+ /// Tokenizes a string using a separator character.
+ ///
+ /// The text.
+ /// The tokenized parts.
+ /// lacks separator character.
+ private string[] TokenizeString(string readText)
+ {
+ if (!readText.Contains(separator))
+ {
+ var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_,
+ filePath, lineNumber, separator);
+ throw new LineParseException(message);
+ }
+ return readText.Split(separator);
+ }
+
+ ///
+ /// Gets the 3D surface line points.
+ ///
+ /// The tokenized string.
+ ///
+ /// A parse error has occurred for the current row, which may be caused by:
+ ///
+ /// - contains a coordinate value that cannot be parsed as a double.
+ /// - contains a number that is too big or too small to be represented with a double.
+ /// - is missing coordinate values to define a proper surface line point.
+ ///
+ ///
+ private Point3D[] GetSurfaceLinePoints(string[] tokenizedString)
+ {
+ const int expectedValuesForPoint = 3;
+
+ var worldCoordinateValues = ParseWorldCoordinateValuesAndHandleParseErrors(tokenizedString);
+ if (worldCoordinateValues.Length % expectedValuesForPoint != 0)
+ {
+ var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet,
+ filePath, lineNumber);
+ throw new LineParseException(message);
+ }
+
+ int coordinateCount = worldCoordinateValues.Length / expectedValuesForPoint;
+ var points = new Point3D[coordinateCount];
+ for (int i = 0; i < coordinateCount; i++)
+ {
+ points[i] = new Point3D
{
- // TODO: Format Error: Row identifier null, empty or whitespace
- Name = tokenizedString.First()
+ X = worldCoordinateValues[i * expectedValuesForPoint],
+ Y = worldCoordinateValues[i * expectedValuesForPoint + 1],
+ Z = worldCoordinateValues[i * expectedValuesForPoint + 2]
};
- surfaceLine.SetGeometry(points);
- return surfaceLine;
}
+ return points;
+ }
- return null;
+ ///
+ /// Gets the name of the surface line.
+ ///
+ /// The tokenized string from which the name should be extrated.
+ /// The name of the surface line.
+ /// Id value is null or empty.
+ private string GetSurfaceLineName(IList tokenizedString)
+ {
+ var name = tokenizedString[0].Trim();
+ if (string.IsNullOrEmpty(name))
+ {
+ var message = string.Format(Resources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId,
+ filePath, lineNumber);
+ throw new LineParseException(message);
+ }
+ return name;
}
///
@@ -174,15 +253,6 @@
}
}
- public void Dispose()
- {
- if (fileReader != null)
- {
- fileReader.Dispose();
- fileReader = null;
- }
- }
-
///
/// Initializes the stream reader for a UTF8 encoded file.
///
@@ -217,10 +287,11 @@
/// Validates the header of the file.
///
/// The reader, which is currently at the header row.
+ /// Row index used in error messaging.
/// The header is not in the required format.
- private void ValidateHeader(TextReader reader)
+ private void ValidateHeader(TextReader reader, int currentLine)
{
- var header = ReadLineAndHandleIOExceptions(reader);
+ var header = ReadLineAndHandleIOExceptions(reader, currentLine);
if (header != null)
{
if (!IsHeaderValid(header))
@@ -245,15 +316,15 @@
/// An I/O exception occurred.
private int CountNonEmptyLines(TextReader reader, int currentLine)
{
- var count = 0;
+ int count = 0, lineNumberForMessage = currentLine;
string line;
- while ((line = ReadLineAndHandleIOExceptions(reader)) != null)
+ while ((line = ReadLineAndHandleIOExceptions(reader, lineNumberForMessage)) != null)
{
if (!String.IsNullOrWhiteSpace(line))
{
count++;
}
- currentLine++;
+ lineNumberForMessage++;
}
return count;
}
@@ -265,15 +336,15 @@
/// Row number for error messaging.
/// The read line, or null when at the end of the file.
/// An critical I/O exception occurred.
- private string ReadLineAndHandleIOExceptions(TextReader reader)
+ private string ReadLineAndHandleIOExceptions(TextReader reader, int currentLine)
{
try
{
return reader.ReadLine();
}
catch (OutOfMemoryException e)
{
- var message = string.Format(Resources.Error_File_0_contains_Line_1_too_big, filePath, lineNumber);
+ var message = string.Format(Resources.Error_File_0_contains_Line_1_too_big, filePath, currentLine);
throw new CriticalFileReadException(message, e);
}
catch (IOException e)
Index: src/Plugins/Wti/Wti.IO/Properties/Resources.Designer.cs
===================================================================
diff -u -r91ec76d4b8a0fcf5962f442021c43f1ffa70743e -raa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9
--- src/Plugins/Wti/Wti.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 91ec76d4b8a0fcf5962f442021c43f1ffa70743e)
+++ src/Plugins/Wti/Wti.IO/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -176,5 +176,33 @@
return ResourceManager.GetString("PipingSurfaceLinesCsvReader_File_0_invalid_header", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} geen verwacht scheidingsteken (het karakter: {2})..
+ ///
+ public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_ {
+ get {
+ return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} ontbrekende waardes om een 3D (X,Y,Z) punt aan te maken..
+ ///
+ public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet {
+ get {
+ return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_tr" +
+ "iplet", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Het bestand '{0}' heeft op regel {1} heeft geen ID..
+ ///
+ public static string PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId {
+ get {
+ return ResourceManager.GetString("PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId", resourceCulture);
+ }
+ }
}
}
Index: src/Plugins/Wti/Wti.IO/Properties/Resources.resx
===================================================================
diff -u -r91ec76d4b8a0fcf5962f442021c43f1ffa70743e -raa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9
--- src/Plugins/Wti/Wti.IO/Properties/Resources.resx (.../Resources.resx) (revision 91ec76d4b8a0fcf5962f442021c43f1ffa70743e)
+++ src/Plugins/Wti/Wti.IO/Properties/Resources.resx (.../Resources.resx) (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -156,4 +156,13 @@
Het bestand '{0}' heeft op regel {1} een waarde dat te groot/klein is om ingelezen te worden.
+
+ Het bestand '{0}' heeft op regel {1} heeft geen ID.
+
+
+ Het bestand '{0}' heeft op regel {1} geen verwacht scheidingsteken (het karakter: {2}).
+
+
+ Het bestand '{0}' heeft op regel {1} ontbrekende waardes om een 3D (X,Y,Z) punt aan te maken.
+
\ No newline at end of file
Index: src/Plugins/Wti/Wti.Plugin/FileImporter/PipingSurfaceLinesCsvImporter.cs
===================================================================
diff -u -r91ec76d4b8a0fcf5962f442021c43f1ffa70743e -raa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9
--- src/Plugins/Wti/Wti.Plugin/FileImporter/PipingSurfaceLinesCsvImporter.cs (.../PipingSurfaceLinesCsvImporter.cs) (revision 91ec76d4b8a0fcf5962f442021c43f1ffa70743e)
+++ src/Plugins/Wti/Wti.Plugin/FileImporter/PipingSurfaceLinesCsvImporter.cs (.../PipingSurfaceLinesCsvImporter.cs) (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -166,7 +166,7 @@
catch (LineParseException e)
{
var message = string.Format(ApplicationResources.PipingSurfaceLinesCsvImporter_ReadPipingSurfaceLines_ParseError_File_0_SurfaceLinesNumber_1_Message_2_,
- path, i+1, e.Message);
+ path, i + 1, e.Message);
log.Error(message);
}
NotifyProgress(stepName, i + 1, itemCount);
Index: test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_IncorrectValueSeparator.csv
===================================================================
diff -u
--- test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_IncorrectValueSeparator.csv (revision 0)
+++ test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_IncorrectValueSeparator.csv (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -0,0 +1,2 @@
+Profielnaam;X1;Y1;Z1;...;Xn;Yn;Zn
+Rotterdam1,94263.0026213,427776.654093,-1.02,94275.9126686,427811.080886,-1.04,94284.0663827,427831.918156,1.25,94294.9380015,427858.191234,1.45,94305.3566362,427889.900123,1.65,94315.0957947,427913.908281,1.66,94325.0614453,427941.766804,1.55,94331.1767309,427960.112661,1.44
\ No newline at end of file
Index: test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_LacksCoordinateValues.csv
===================================================================
diff -u
--- test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_LacksCoordinateValues.csv (revision 0)
+++ test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/InvalidRow_LacksCoordinateValues.csv (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -0,0 +1,2 @@
+Profielnaam;X1;Y1;Z1;...;Xn;Yn;Zn
+InvalidRow1
\ No newline at end of file
Index: test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_IncompleteCoordinateTriplets.csv
===================================================================
diff -u
--- test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_IncompleteCoordinateTriplets.csv (revision 0)
+++ test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_IncompleteCoordinateTriplets.csv (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -0,0 +1,3 @@
+Profielnaam;X1;Y1;Z1;...;Xn;Yn;Zn
+LacksOneCoordinate;94263.0026213;427776.654093;-1.02;94275.9126686;427811.080886;-1.04;94284.0663827;1.25;94294.9380015;427858.191234;1.45;94305.3566362;427889.900123;1.65;94315.0957947;427913.908281;1.66;94325.0614453;427941.766804;1.55;94331.1767309;427960.112661;1.44
+LacksTwoCoordinates;2.3;0;1.0;2.0;4.4;0;1.1
\ No newline at end of file
Index: test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_LacksId.csv
===================================================================
diff -u
--- test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_LacksId.csv (revision 0)
+++ test-data/Plugins/Wti/IO/PipingSurfaceLinesCsvReader/TwoInvalidRows_LacksId.csv (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -0,0 +1,3 @@
+Profielnaam;X1;Y1;Z1;...;Xn;Yn;Zn
+;94263.0026213;427776.654093;-1.02;94275.9126686;427811.080886;-1.04;94284.0663827;427831.918156;1.25;94294.9380015;427858.191234;1.45;94305.3566362;427889.900123;1.65;94315.0957947;427913.908281;1.66;94325.0614453;427941.766804;1.55;94331.1767309;427960.112661;1.44
+ ;2.3;0;1.0;5.7;0;2.0;4.4;0;1.1
\ No newline at end of file
Index: test/Plugins/Wti/Wti.IO.Test/PipingSurfaceLinesCsvReaderTest.cs
===================================================================
diff -u -r91ec76d4b8a0fcf5962f442021c43f1ffa70743e -raa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9
--- test/Plugins/Wti/Wti.IO.Test/PipingSurfaceLinesCsvReaderTest.cs (.../PipingSurfaceLinesCsvReaderTest.cs) (revision 91ec76d4b8a0fcf5962f442021c43f1ffa70743e)
+++ test/Plugins/Wti/Wti.IO.Test/PipingSurfaceLinesCsvReaderTest.cs (.../PipingSurfaceLinesCsvReaderTest.cs) (revision aa2e48b57a92d8f3703cb27e92bb538bfc5b6ff9)
@@ -422,6 +422,102 @@
}
}
+ [Test]
+ public void ReadLine_FileLacksIds_ThrowLineParseException()
+ {
+ // Setup
+ string path = Path.Combine(testDataPath, "TwoInvalidRows_LacksId.csv");
+
+ // Precondition
+ Assert.IsTrue(File.Exists(path));
+
+ using (var reader = new PipingSurfaceLinesCsvReader(path))
+ {
+ // Call
+ TestDelegate call = () => reader.ReadLine();
+
+ // Assert
+ // 1st line has no text at all:
+ var exception = Assert.Throws(call);
+ var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId, path, 2);
+ Assert.AreEqual(expectedMessage, exception.Message);
+
+ // 2nd line has only whitespace text:
+ expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_NoId, path, 3);
+ exception = Assert.Throws(call);
+ Assert.AreEqual(expectedMessage, exception.Message);
+ }
+ }
+
+ [Test]
+ public void ReadLine_IncorrectValueSeparator_ThrowLineParseException()
+ {
+ // Setup
+ string path = Path.Combine(testDataPath, "InvalidRow_IncorrectValueSeparator.csv");
+
+ // Precondition
+ Assert.IsTrue(File.Exists(path));
+
+ using (var reader = new PipingSurfaceLinesCsvReader(path))
+ {
+ // Call
+ TestDelegate call = () => reader.ReadLine();
+
+ // Assert
+ var exception = Assert.Throws(call);
+ var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_, path, 2, ';');
+ Assert.AreEqual(expectedMessage, exception.Message);
+ }
+ }
+
+ [Test]
+ public void ReadLine_FileLacksCoordinateValues_ThrowLineParseException()
+ {
+ // Setup
+ string path = Path.Combine(testDataPath, "InvalidRow_LacksCoordinateValues.csv");
+
+ // Precondition
+ Assert.IsTrue(File.Exists(path));
+
+ using (var reader = new PipingSurfaceLinesCsvReader(path))
+ {
+ // Call
+ TestDelegate call = () => reader.ReadLine();
+
+ // Assert
+ var exception = Assert.Throws(call);
+ var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_separator_2_, path, 2, ';');
+ Assert.AreEqual(expectedMessage, exception.Message);
+ }
+ }
+
+ [Test]
+ public void ReadLine_FileHasIncompleteCoordinateTriplets_ThrowLineParseException()
+ {
+ // Setup
+ string path = Path.Combine(testDataPath, "TwoInvalidRows_IncompleteCoordinateTriplets.csv");
+
+ // Precondition
+ Assert.IsTrue(File.Exists(path));
+
+ using (var reader = new PipingSurfaceLinesCsvReader(path))
+ {
+ // Call
+ TestDelegate call = () => reader.ReadLine();
+
+ // Assert
+ // 1st row lacks 1 coordinate value:
+ var exception = Assert.Throws(call);
+ var expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet, path, 2);
+ Assert.AreEqual(expectedMessage, exception.Message);
+
+ // 2nd row lacks 2 coordinate values:
+ exception = Assert.Throws(call);
+ expectedMessage = string.Format(IOResources.PipingSurfaceLinesCsvReader_ReadLine_File_0_Line_1_Lacks_values_for_coordinate_triplet, path, 3);
+ Assert.AreEqual(expectedMessage, exception.Message);
+ }
+ }
+
private void DoReadLine_OpenedValidFileWithHeaderAndTwoSurfaceLines_ReturnCreatedSurfaceLine()
{
// Setup