Index: Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs =================================================================== diff -u -rd73c509c93f18a87da76086c871eca2a2c903e12 -r0615f3f2d1a71890c749543b2ac54372be10d259 --- Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs (.../IDataReaderExtensions.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) +++ Core/Common/src/Core.Common.IO/Readers/IDataReaderExtensions.cs (.../IDataReaderExtensions.cs) (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -35,6 +35,8 @@ /// The data reader to read a column of a certain type from. /// The name of the column to read from. /// The read value from the column with name . + /// Thrown when is not present in the read + /// data row. /// Thrown when or /// is null. /// Thrown when the value in the column was not of type . @@ -49,11 +51,20 @@ throw new ArgumentNullException("columnName"); } - var value = dataReader[columnName]; var conversionType = typeof(T); + object value; try { + value = dataReader[columnName]; + } + catch (IndexOutOfRangeException) + { + throw new ArgumentException(string.Format("Column '{0}' not defined for data row.", columnName), "columnName"); + } + + try + { return (T) Convert.ChangeType(value, conversionType); } catch (InvalidCastException) Index: Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs =================================================================== diff -u -rd73c509c93f18a87da76086c871eca2a2c903e12 -r0615f3f2d1a71890c749543b2ac54372be10d259 --- Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs (.../IDataReaderExtensionsTest.cs) (revision d73c509c93f18a87da76086c871eca2a2c903e12) +++ Core/Common/test/Core.Common.IO.Test/Readers/IDataReaderExtensionsTest.cs (.../IDataReaderExtensionsTest.cs) (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -24,6 +24,7 @@ using System.Globalization; using Core.Common.IO.Exceptions; using Core.Common.IO.Readers; +using Core.Common.TestUtil; using NUnit.Framework; using Rhino.Mocks; @@ -62,17 +63,39 @@ } [Test] + public void Read_NotExistingColumnName_ThrowsArgumentException() + { + // Setup + var mockRepository = new MockRepository(); + var dataReader = mockRepository.Stub(); + var columnName = "SomeColumn"; + dataReader.Stub(dr => dr[columnName]).Throw(new IndexOutOfRangeException()); + mockRepository.ReplayAll(); + + // Call + TestDelegate test = () => dataReader.Read(columnName); + + // Assert + ArgumentException exception = TestHelper.AssertThrowsArgumentExceptionAndTestMessage( + test, "Column \'SomeColumn\' not defined for data row."); + var paramName = exception.ParamName; + Assert.AreEqual("columnName", paramName); + + mockRepository.VerifyAll(); + } + + [Test] public void Read_NumberWithInvalidFormat_ThrowsInvalidCastException() { // Setup var mockRepository = new MockRepository(); var dataReader = mockRepository.Stub(); - string columName = "SomeColumn"; - dataReader.Stub(dr => dr[columName]).Return("3..2"); + string columnName = "SomeColumn"; + dataReader.Stub(dr => dr[columnName]).Return("3..2"); mockRepository.ReplayAll(); // Call - TestDelegate test = () => dataReader.Read(columName); + TestDelegate test = () => dataReader.Read(columnName); // Assert var message = Assert.Throws(test).Message; @@ -87,13 +110,13 @@ // Setup var mockRepository = new MockRepository(); var dataReader = mockRepository.Stub(); - string columName = "SomeColumn"; + string columnName = "SomeColumn"; var value = 3.9; - dataReader.Stub(dr => dr[columName]).Return(value); + dataReader.Stub(dr => dr[columnName]).Return(value); mockRepository.ReplayAll(); // Call - TestDelegate test = () => dataReader.Read(columName); + TestDelegate test = () => dataReader.Read(columnName); // Assert var message = Assert.Throws(test).Message; @@ -111,12 +134,12 @@ // Setup var mockRepository = new MockRepository(); var dataReader = mockRepository.Stub(); - string columName = "SomeColumn"; - dataReader.Stub(dr => dr[columName]).Return(3e139); + string columnName = "SomeColumn"; + dataReader.Stub(dr => dr[columnName]).Return(3e139); mockRepository.ReplayAll(); // Call - TestDelegate test = () => dataReader.Read(columName); + TestDelegate test = () => dataReader.Read(columnName); // Assert var message = Assert.Throws(test).Message; @@ -129,16 +152,16 @@ public void Read_UsingSameTypeAsColumnType_ReturnsTypedValue() { // Setup - string columName = "SomeColumn"; + string columnName = "SomeColumn"; var testValue = "testValue"; var mockRepository = new MockRepository(); var dataReader = mockRepository.Stub(); - dataReader.Stub(dr => dr[columName]).Return(testValue); + dataReader.Stub(dr => dr[columnName]).Return(testValue); mockRepository.ReplayAll(); // Call - string result = dataReader.Read(columName); + string result = dataReader.Read(columnName); // Assert Assert.AreEqual(testValue, result); Index: Core/Components/src/Core.Components.Gis.IO/Readers/ShapeFileReaderBase.cs =================================================================== diff -u -r58e275211395fc690df2706ccdaff082ecf7b544 -r0615f3f2d1a71890c749543b2ac54372be10d259 --- Core/Components/src/Core.Components.Gis.IO/Readers/ShapeFileReaderBase.cs (.../ShapeFileReaderBase.cs) (revision 58e275211395fc690df2706ccdaff082ecf7b544) +++ Core/Components/src/Core.Components.Gis.IO/Readers/ShapeFileReaderBase.cs (.../ShapeFileReaderBase.cs) (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -20,6 +20,7 @@ // All rights reserved. using System; +using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; @@ -116,14 +117,17 @@ /// /// The whose metadata will be updated. /// The index of the feature in the shapefile on which the is based. + /// Attributes with value are translated to a null value in the + /// . protected void CopyMetaDataIntoFeature(MapFeature targetFeature, int sourceFeatureIndex) { DataTable table = ShapeFile.GetAttributes(sourceFeatureIndex, 1); DataRow dataRow = table.Rows[0]; for (int i = 0; i < table.Columns.Count; i++) { - targetFeature.MetaData[table.Columns[i].ColumnName] = dataRow[i]; + var value = dataRow[i] is DBNull ? null : dataRow[i]; + targetFeature.MetaData[table.Columns[i].ColumnName] = value; } } } Index: Core/Components/test/Core.Components.Gis.IO.Test/Readers/ShapeFileReaderBaseTest.cs =================================================================== diff -u -red96d38a758365e4c0f117def83a2926c589c18a -r0615f3f2d1a71890c749543b2ac54372be10d259 --- Core/Components/test/Core.Components.Gis.IO.Test/Readers/ShapeFileReaderBaseTest.cs (.../ShapeFileReaderBaseTest.cs) (revision ed96d38a758365e4c0f117def83a2926c589c18a) +++ Core/Components/test/Core.Components.Gis.IO.Test/Readers/ShapeFileReaderBaseTest.cs (.../ShapeFileReaderBaseTest.cs) (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -20,10 +20,14 @@ // All rights reserved. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using Core.Common.IO.Exceptions; using Core.Common.TestUtil; using Core.Components.Gis.Data; +using Core.Components.Gis.Features; +using Core.Components.Gis.Geometries; using Core.Components.Gis.IO.Readers; using DotSpatial.Data; using NUnit.Framework; @@ -46,7 +50,6 @@ // Assert Assert.IsInstanceOf(reader); Assert.AreEqual(testFilePath, reader.GetFilePath); - Assert.IsNull(reader.GetShapeFile); } } @@ -115,9 +118,92 @@ TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, expectedMessage); } + [Test] + public void CopyMetaDataIntoFeature_AllValidValues_MetaDataAddedToFeature() + { + // Setup + string validFilePath = TestHelper.GetTestDataPath(TestDataPath.Core.Components.Gis.IO, "traject_10-1.shp"); + + var reader = new TestShapeFileReaderBase(validFilePath); + var targetFeature = new MapFeature(new MapGeometry[0]); + + // Call + reader.PublicCopyMetaDataIntoFeature(targetFeature, 0); + + // Assert + Assert.AreEqual("A", targetFeature.MetaData["CATEGORIE"]); + Assert.AreEqual("10", targetFeature.MetaData["DIJKRING"]); + Assert.AreEqual(19190.35, targetFeature.MetaData["LENGTE_TRJ"]); + Assert.AreEqual("1:1000", targetFeature.MetaData["Ondergrens"]); + Assert.AreEqual("1:3000", targetFeature.MetaData["Signalerin"]); + Assert.AreEqual("10-1", targetFeature.MetaData["TRAJECT_ID"]); + } + + [Test] + public void CopyMetaDataIntoFeature_MultipleFeaturesAllValidValues_MetaDataAddedToFeature() + { + // Setup + string validFilePath = TestHelper.GetTestDataPath(TestDataPath.Core.Components.Gis.IO, "Multiple_Polygon_with_ID.shp"); + + var reader = new TestShapeFileReaderBase(validFilePath); + var features = new List(); + + for (int i = 0; i < 4; i++) + { + var targetFeature = new MapFeature(new MapGeometry[0]); + + // Call + reader.PublicCopyMetaDataIntoFeature(targetFeature, i); + + features.Add(targetFeature); + } + + // Assert + CollectionAssert.AreEqual(new [] { 4,3,2,1 } , features.Select(f => f.MetaData["id"])); + } + + [Test] + public void CopyMetaDataIntoFeature_DBNullValuesForColumn_MetaDataWithNullValueForAttribute() + { + // Setup + string fileWithDbNullValues = TestHelper.GetTestDataPath(TestDataPath.Core.Components.Gis.IO, "Shape_DBNullSignalerinValue.shp"); + + var reader = new TestShapeFileReaderBase(fileWithDbNullValues); + var targetFeature = new MapFeature(new MapGeometry[0]); + + // Call + reader.PublicCopyMetaDataIntoFeature(targetFeature, 0); + + // Assert + Assert.IsNull(targetFeature.MetaData["Signalerin"]); + } + + [Test] + public void CopyMetaDataIntoFeature_DBNullValuesForEachType_MetaDataWithNullValues() + { + // Setup + string fileWithDbNullValues = TestHelper.GetTestDataPath(TestDataPath.Core.Components.Gis.IO, "Attribute_EachTypeNullValue_QGis.shp"); + + var reader = new TestShapeFileReaderBase(fileWithDbNullValues); + var targetFeature = new MapFeature(new MapGeometry[0]); + + // Call + reader.PublicCopyMetaDataIntoFeature(targetFeature, 3); + + // Assert + Assert.IsNull(targetFeature.MetaData["attInteg2"]); + Assert.IsNull(targetFeature.MetaData["attInteg64"]); + Assert.IsNull(targetFeature.MetaData["attDecimal"]); + Assert.IsNull(targetFeature.MetaData["attString"]); + Assert.IsNull(targetFeature.MetaData["attDate"]); + } + private class TestShapeFileReaderBase : ShapeFileReaderBase { - public TestShapeFileReaderBase(string filePath) : base(filePath) {} + public TestShapeFileReaderBase(string filePath) : base(filePath) + { + ShapeFile = Shapefile.OpenFile(filePath); + } public string GetFilePath { @@ -149,6 +235,11 @@ { return null; } + + public void PublicCopyMetaDataIntoFeature(MapFeature targetFeature, int sourceFeatureIndex) + { + CopyMetaDataIntoFeature(targetFeature, sourceFeatureIndex); + } } } } \ No newline at end of file Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.dbf =================================================================== diff -u Binary files differ Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.prj =================================================================== diff -u --- Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.prj (revision 0) +++ Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.prj (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -0,0 +1 @@ +PROJCS["Amersfoort_RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Double_Stereographic"],PARAMETER["latitude_of_origin",52.15616055555555],PARAMETER["central_meridian",5.38763888888889],PARAMETER["scale_factor",0.9999079],PARAMETER["false_easting",155000],PARAMETER["false_northing",463000],UNIT["Meter",1]] \ No newline at end of file Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.qpj =================================================================== diff -u --- Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.qpj (revision 0) +++ Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.qpj (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -0,0 +1 @@ +PROJCS["Amersfoort / RD New",GEOGCS["Amersfoort",DATUM["Amersfoort",SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],TOWGS84[565.4171,50.3319,465.5524,-0.398957,0.343988,-1.87740,4.0725],AUTHORITY["EPSG","6289"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4289"]],PROJECTION["Oblique_Stereographic"],PARAMETER["latitude_of_origin",52.15616055555555],PARAMETER["central_meridian",5.38763888888889],PARAMETER["scale_factor",0.9999079],PARAMETER["false_easting",155000],PARAMETER["false_northing",463000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],AUTHORITY["EPSG","28992"]] Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.shp =================================================================== diff -u Binary files differ Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Attribute_EachTypeNullValue_QGis.shx =================================================================== diff -u Binary files differ Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.dbf =================================================================== diff -u Binary files differ Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.prj =================================================================== diff -u --- Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.prj (revision 0) +++ Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.prj (revision 0615f3f2d1a71890c749543b2ac54372be10d259) @@ -0,0 +1 @@ +PROJCS["RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Double_Stereographic"],PARAMETER["False_Easting",155000.0],PARAMETER["False_Northing",463000.0],PARAMETER["Central_Meridian",5.38763888888889],PARAMETER["Scale_Factor",0.9999079],PARAMETER["Latitude_Of_Origin",52.15616055555555],UNIT["Meter",1.0]] \ No newline at end of file Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.shp =================================================================== diff -u Binary files differ Index: Core/Components/test/Core.Components.Gis.IO.Test/test-data/Shape_DBNullSignalerinValue.shx =================================================================== diff -u Binary files differ