Permalink
Browse files

Fixes the CsvTokenizer issue reading the last value of a line

  • Loading branch information...
1 parent 3a03b5a commit 1ea8cbbac123525d720b89c2190c12d0a20e6376 @jmarnold jmarnold committed Dec 3, 2012
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using FubuCore.Binding.Values;
+using FubuCore.Csv;
+using FubuCore.Reflection;
+using FubuTestingSupport;
+using NUnit.Framework;
+
+namespace FubuCore.Testing.Csv
+{
+ [TestFixture]
+ public class creating_a_value_source_when_all_values_exist
+ {
+ private IList<ColumnDefinition> theColumns;
+ private IList<string> theData;
+
+ [SetUp]
+ public void SetUp()
+ {
+ theData = new List<string>();
+ theColumns = new List<ColumnDefinition>();
+
+ theData.Add("Test");
+ theData.Add("true");
+ theData.Add("1");
+
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Name)));
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Flag)));
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Count)));
+ }
+
+ private IValueSource theValues { get { return new CsvData(theData).ToValueSource(theColumns); } }
+
+ [Test]
+ public void the_values_are_indexed_by_accessor()
+ {
+ get(x => x.Name).ShouldEqual("Test");
+ get(x => x.Flag).ShouldEqual("true");
+ get(x => x.Count).ShouldEqual("1");
+ }
+
+ private Accessor accessor(Expression<Func<TestCsvObject, object>> expression)
+ {
+ return expression.ToAccessor();
+ }
+
+ private object get(Expression<Func<TestCsvObject, object>> expression)
+ {
+ return theValues.Get(accessor(expression).Name);
+ }
+ }
+}
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using FubuCore.Binding.Values;
+using FubuCore.Csv;
+using FubuCore.Reflection;
+using FubuTestingSupport;
+using NUnit.Framework;
+
+namespace FubuCore.Testing.Csv
+{
+ [TestFixture]
+ public class creating_a_value_source_when_not_all_values_exist
+ {
+ private IList<ColumnDefinition> theColumns;
+ private IList<string> theData;
+
+ [SetUp]
+ public void SetUp()
+ {
+ theData = new List<string>();
+ theColumns = new List<ColumnDefinition>();
+
+ theData.Add("Test");
+ theData.Add("true");
+
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Name)));
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Flag)));
+ theColumns.Add(new ColumnDefinition(accessor(x => x.Count)));
+ }
+
+ private IValueSource theValues { get { return new CsvData(theData).ToValueSource(theColumns); } }
+
+ [Test]
+ public void the_value_is_null_if_it_doesnt_exist()
+ {
+ get(x => x.Count).ShouldBeNull();
+ }
+
+ private Accessor accessor(Expression<Func<TestCsvObject, object>> expression)
+ {
+ return expression.ToAccessor();
+ }
+
+ private object get(Expression<Func<TestCsvObject, object>> expression)
+ {
+ return theValues.Get(accessor(expression).Name);
+ }
+ }
+}
@@ -0,0 +1,32 @@
+using System.IO;
+using FubuCore.Csv;
+using NUnit.Framework;
+
+namespace FubuCore.Testing.Csv
+{
+ [TestFixture]
+ public class when_processing_a_csv_file_with_empty_last_column : CsvReaderHarness<TestCsvMapping, TestCsvObject>
+ {
+ protected override void writeFile(StreamWriter writer)
+ {
+ writer.WriteLine("Count|Flag|Name");
+ writer.WriteLine("1|true|");
+ }
+
+ protected override void configureRequest(CsvRequest<TestCsvObject> request)
+ {
+ request.HeadersExist = true;
+ request.UseHeaderOrdering = true;
+
+ request.Delimiter = '|';
+ }
+
+ [Test]
+ public void parses_the_last_value()
+ {
+ var t1 = new TestCsvObject { Name = null, Count = 1, Flag = true };
+
+ theResultsAre(t1);
+ }
+ }
+}
@@ -82,10 +82,13 @@
<Compile Include="Csv\ColumnDefinitionTester.cs" />
<Compile Include="Csv\ColumnExpressionTester.cs" />
<Compile Include="Csv\ColumnMappingTester.cs" />
+ <Compile Include="Csv\creating_a_value_source_when_not_all_values_exist.cs" />
+ <Compile Include="Csv\creating_a_value_source_when_all_values_exist.cs" />
<Compile Include="Csv\CsvReaderHarness.cs" />
<Compile Include="Csv\CsvRequestTester.cs" />
<Compile Include="Csv\CsvTokenizerTester.cs" />
<Compile Include="Csv\SpecialCharacterHeaderHarness.cs" />
+ <Compile Include="Csv\when_processing_a_csv_file_with_empty_last_column.cs" />
<Compile Include="Csv\when_processing_a_csv_file_with_headers_and_aliases.cs" />
<Compile Include="Csv\when_processing_a_csv_file_without_headers.cs" />
<Compile Include="Csv\TestCsvObject.cs" />
@@ -41,7 +41,7 @@ ColumnDefinition IColumnMapping.ColumnFor(Accessor accessor)
IValueSource IColumnMapping.ValueSource(CsvData data)
{
- return sourceFor(_columns, data);
+ return data.ToValueSource(_columns);
}
IValueSource IColumnMapping.ValueSource(CsvData data, CsvData headers)
@@ -50,21 +50,7 @@ IValueSource IColumnMapping.ValueSource(CsvData data, CsvData headers)
.Values
.Select(x => ((IColumnMapping)this).ColumnFor(x));
- return sourceFor(columns, data);
- }
-
- private IValueSource sourceFor(IEnumerable<ColumnDefinition> columns, CsvData data)
- {
- var index = 0;
- var dictionary = new Dictionary<string, string>();
- columns.Each(col =>
- {
- // TODO -- Harden this
- dictionary.Add(col.Accessor.Name, data.Values[index]);
- ++index;
- });
-
- return new FlatValueSource(dictionary);
+ return data.ToValueSource(columns);
}
}
}
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+using FubuCore.Binding.Values;
namespace FubuCore.Csv
{
@@ -10,6 +11,27 @@ public CsvData(IEnumerable<string> values)
Values = values.ToArray();
}
- public string[] Values { get; private set; }
+ public string[] Values { get; private set; }
+
+ public IValueSource ToValueSource(IEnumerable<ColumnDefinition> columns)
+ {
+ var index = 0;
+ var bounds = Values.Length;
+ var dictionary = new Dictionary<string, string>();
+
+ columns.Each(col =>
+ {
+ string value = null;
+ if(index < bounds)
+ {
+ value = Values[index];
+ }
+
+ dictionary.Add(col.Accessor.Name, value);
+ ++index;
+ });
+
+ return new FlatValueSource(dictionary);
+ }
}
}

0 comments on commit 1ea8cbb

Please sign in to comment.