diff --git a/CHANGELOG.md b/CHANGELOG.md index 27e580f..f6b7c9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.11.0 (2020-10-09) +**Summary* - Allow handling unrecognized rows when using schema selectors. + +Previously, if a record was encountered that could be handled by any of the configured schemas, the selector would throw a generic `FlatFilesException`. Now, a `RecordProcessingException`is thrown instead, which can be ignored causing the record to be skipped. + ## 4.10.0 (2020-10-06) **Summary** - Add the ability to explicitly write the schema using typed writers. diff --git a/FlatFiles.Test/FixedLengthMultipleSchemaTester.cs b/FlatFiles.Test/FixedLengthMultipleSchemaTester.cs index 5882532..37d86fe 100644 --- a/FlatFiles.Test/FixedLengthMultipleSchemaTester.cs +++ b/FlatFiles.Test/FixedLengthMultipleSchemaTester.cs @@ -155,6 +155,27 @@ 46.9 23.45 True Assert.IsFalse(reader.Read()); } + [TestMethod] + [ExpectedException(typeof(RecordProcessingException))] + public void TestReader_UnknownType() + { + var stringReader = new StringReader("What's this weird thing?"); + var selector = getSchemaSelector(); + var reader = new FixedLengthReader(stringReader, selector); + + reader.Read(); + } + + [TestMethod] + public void TestReader_UnknownType_IgnoreUnknown_SkipsRecord() + { + var stringReader = new StringReader("What's this weird thing?"); + var selector = getSchemaSelector(); + var reader = new FixedLengthReader(stringReader, selector); + reader.RecordError += (o, e) => e.IsHandled = true; + Assert.IsFalse(reader.Read()); + } + private FixedLengthTypeMapperSelector getTypeMapperSelector() { var selector = new FixedLengthTypeMapperSelector(); diff --git a/FlatFiles.Test/SeparatedValueMultipleSchemaTester.cs b/FlatFiles.Test/SeparatedValueMultipleSchemaTester.cs index 3a4a95b..fd5bbdf 100644 --- a/FlatFiles.Test/SeparatedValueMultipleSchemaTester.cs +++ b/FlatFiles.Test/SeparatedValueMultipleSchemaTester.cs @@ -201,6 +201,27 @@ public void TestTypeMapper_ReadThreeTypes_WithMetadataRecord() Assert.IsFalse(reader.Read()); } + [TestMethod] + [ExpectedException(typeof(RecordProcessingException))] + public void TestReader_UnknownType() + { + var stringReader = new StringReader("What's this weird thing?"); + var selector = getSchemaSelector(); + var reader = new SeparatedValueReader(stringReader, selector); + + reader.Read(); + } + + [TestMethod] + public void TestReader_UnknownType_IgnoreUnknown_SkipsRecord() + { + var stringReader = new StringReader("What's this weird thing?"); + var selector = getSchemaSelector(); + var reader = new SeparatedValueReader(stringReader, selector); + reader.RecordError += (o, e) => e.IsHandled = true; + Assert.IsFalse(reader.Read()); + } + private SeparatedValueTypeMapperSelector getTypeMapperSelector(bool hasMetadata = false) { var selector = new SeparatedValueTypeMapperSelector(); diff --git a/FlatFiles/FixedLengthReader.cs b/FlatFiles/FixedLengthReader.cs index 727b6e5..ce7e2fb 100644 --- a/FlatFiles/FixedLengthReader.cs +++ b/FlatFiles/FixedLengthReader.cs @@ -413,7 +413,13 @@ private FixedLengthSchema GetSchema(string record) { return metadata.ExecutionContext.Schema; } - return schemaSelector.GetSchema(record); + FixedLengthSchema schema = schemaSelector.GetSchema(record); + if (schema != null) + { + return schema; + } + ProcessError(new RecordProcessingException(metadata, Resources.MissingMatcher)); + return null; } private string ReadNextRecord() diff --git a/FlatFiles/FixedLengthSchemaSelector.cs b/FlatFiles/FixedLengthSchemaSelector.cs index dddb0cb..11b1a8f 100644 --- a/FlatFiles/FixedLengthSchemaSelector.cs +++ b/FlatFiles/FixedLengthSchemaSelector.cs @@ -92,7 +92,7 @@ internal FixedLengthSchema GetSchema(string record) defaultMatcher.Action?.Invoke(); return defaultMatcher.Schema; } - throw new FlatFileException(Resources.MissingMatcher); + return null; } private class SchemaMatcher diff --git a/FlatFiles/FlatFiles.csproj b/FlatFiles/FlatFiles.csproj index d888413..8c5af23 100644 --- a/FlatFiles/FlatFiles.csproj +++ b/FlatFiles/FlatFiles.csproj @@ -10,17 +10,17 @@ https://github.com/jehugaleahsa/FlatFiles.git git csv;comma;tab;separated;value;delimited;flat;file;fixed;width;fixed-width;length;fixed-length;parser;parsing;parse - Allow explicitly writing the schema using typed mappers. + Allow handling unrecognized rows when using schema selectors. true FlatFiles.snk - 4.10.0 + 4.11.0 8.0 - 4.10.0.0 - 4.10.0.0 + 4.11.0.0 + 4.11.0.0 UNLICENSE.txt icon.png diff --git a/FlatFiles/SeparatedValueReader.cs b/FlatFiles/SeparatedValueReader.cs index 54c3c81..3c728af 100644 --- a/FlatFiles/SeparatedValueReader.cs +++ b/FlatFiles/SeparatedValueReader.cs @@ -360,11 +360,24 @@ private SeparatedValueSchema GetSchema(string[] rawValues) { return metadata.ExecutionContext.Schema; } - return schemaSelector.GetSchema(rawValues); + SeparatedValueSchema schema = schemaSelector.GetSchema(rawValues); + if (schema != null) + { + return schema; + } + ProcessError(new RecordProcessingException(metadata, Resources.MissingMatcher)); + return null; } private bool IsSkipped(string[] values) { + if (metadata.ExecutionContext.Schema == null && schemaSelector != null) + { + // A schema was not found by the selector for the given record. + // If we got here then we know the raised exception was handled and suppressed. + // Therefore we skip the record and go on to the next one. + return true; + } if (RecordRead == null) { return false; diff --git a/FlatFiles/SeparatedValueSchemaSelector.cs b/FlatFiles/SeparatedValueSchemaSelector.cs index f9179c1..b3a9726 100644 --- a/FlatFiles/SeparatedValueSchemaSelector.cs +++ b/FlatFiles/SeparatedValueSchemaSelector.cs @@ -99,7 +99,7 @@ internal SeparatedValueSchema GetSchema(string[] values) defaultMatcher.Action?.Invoke(); return defaultMatcher.Schema; } - throw new FlatFileException(Resources.MissingMatcher); + return null; } private class SchemaMatcher