diff --git a/README.md b/README.md index 8ad7122..51fda98 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ To configure the verification a JSON file is used with the following format: "1": { "name": "ID", "isRequired": true, - "unique": true + "unique": true, + "trim": true }, "2": { "name": "DOB", @@ -54,6 +55,8 @@ The columns __require__ the number, which is the ordinal of the column in the in ``` { + // trim value before checking + "trim": true|false, // validates the column has content "isRequired": true|false, // validates the content is unique in this column across the full file diff --git a/src/Validate.Lib/ColumnValidatorConfiguration.cs b/src/Validate.Lib/ColumnValidatorConfiguration.cs index fe08d0d..4b5706a 100644 --- a/src/Validate.Lib/ColumnValidatorConfiguration.cs +++ b/src/Validate.Lib/ColumnValidatorConfiguration.cs @@ -14,5 +14,7 @@ public class ColumnValidatorConfiguration public bool IsNumeric { get; set; } public bool IsRequired { get; set; } + + public bool Trim { get; set; } } } diff --git a/src/Validate.Lib/ConfigurationConvertor.cs b/src/Validate.Lib/ConfigurationConvertor.cs index 99f91c8..e02e961 100644 --- a/src/Validate.Lib/ConfigurationConvertor.cs +++ b/src/Validate.Lib/ConfigurationConvertor.cs @@ -48,6 +48,7 @@ private void ConvertColumns() if (!string.IsNullOrWhiteSpace(columnConfig.Value.Pattern)) group.Add(new TextFormatValidator(columnConfig.Value.Pattern)); if (columnConfig.Value.IsNumeric) group.Add(new NumberValidator()); if (columnConfig.Value.IsRequired) group.Add(new NotNullableValidator()); + if (columnConfig.Value.Trim) _converted.TrimBeforeCheck.Add(columnConfig.Key); _converted.Columns.Add(columnConfig.Key, group); } diff --git a/src/Validate.Lib/ConvertedValidators.cs b/src/Validate.Lib/ConvertedValidators.cs index 98c4f58..953a475 100644 --- a/src/Validate.Lib/ConvertedValidators.cs +++ b/src/Validate.Lib/ConvertedValidators.cs @@ -9,10 +9,13 @@ internal class ConvertedValidators public ConvertedValidators() { Columns = new Dictionary>(); + TrimBeforeCheck = new List(); } public Dictionary> Columns { get; private set; } + public List TrimBeforeCheck { get; private set; } + public string RowSeperator { get; set; } public string ColumnSeperator { get; set; } diff --git a/src/Validate.Lib/Validator.cs b/src/Validate.Lib/Validator.cs index 7395dcb..33153ff 100644 --- a/src/Validate.Lib/Validator.cs +++ b/src/Validate.Lib/Validator.cs @@ -124,7 +124,11 @@ private void TransferConvertedColumns(ConvertedValidators converted) { foreach (IValidator columnValidator in column.Value) { - _rowValidator.AddColumnValidator(column.Key, columnValidator); + _rowValidator.AddColumnValidator( + column.Key, + columnValidator, + converted.TrimBeforeCheck.Contains(column.Key) + ); } } } diff --git a/src/Validate.Lib/Validators/RowValidator.cs b/src/Validate.Lib/Validators/RowValidator.cs index 8f9aaf7..037cc96 100644 --- a/src/Validate.Lib/Validators/RowValidator.cs +++ b/src/Validate.Lib/Validators/RowValidator.cs @@ -13,6 +13,7 @@ namespace FormatValidator.Validators internal class RowValidator { private ValidatorGroup[] _columns; + private List _trimBeforeCheck; private RowValidationError _errorInformation; private string _columnSeperator; @@ -20,6 +21,7 @@ public RowValidator() { _errorInformation = new RowValidationError(); _columns = new ValidatorGroup[0]; + _trimBeforeCheck = new List(); } public RowValidator(string columnSeperator) : this() @@ -42,7 +44,13 @@ public bool IsValid(string toCheck) { if (currentColumn < _columns.Length) { - bool result = _columns[currentColumn].IsValid(parts[currentColumn]); + string value = parts[currentColumn]; + if (_trimBeforeCheck.Contains(currentColumn)) + { + value = value.Trim(); + } + + bool result = _columns[currentColumn].IsValid(value); IList newErrors = _columns[currentColumn].GetErrors(); _errorInformation.Errors.AddRange(newErrors); @@ -78,11 +86,15 @@ public void ClearErrors() } } - public void AddColumnValidator(int toColumn, IValidator validator) + public void AddColumnValidator(int toColumn, IValidator validator, bool trim = false) { CheckAndResizeColumnList(toColumn); - - _columns[toColumn - 1].Add(validator); + int index = toColumn - 1; + _columns[index].Add(validator); + if (trim) + { + _trimBeforeCheck.Add(index); + } } public List GetColumnValidators() diff --git a/test/ValidateTests/Data/Configuration/testfile-configuration.json b/test/ValidateTests/Data/Configuration/testfile-configuration.json index c52d3c4..6c4fcab 100644 --- a/test/ValidateTests/Data/Configuration/testfile-configuration.json +++ b/test/ValidateTests/Data/Configuration/testfile-configuration.json @@ -10,7 +10,8 @@ }, "2": { "name": "NAME", - "maxLength": 10 + "maxLength": 10, + "trim": true }, "3": { "name": "DOB", @@ -18,7 +19,8 @@ }, "4": { "name": "USERNAME", - "isRequired": true + "isRequired": true, + "trim": true } } } diff --git a/test/ValidateTests/Data/headers-testfile-1.csv b/test/ValidateTests/Data/headers-testfile-1.csv index 37802e2..bfbedfb 100644 --- a/test/ValidateTests/Data/headers-testfile-1.csv +++ b/test/ValidateTests/Data/headers-testfile-1.csv @@ -1,5 +1,5 @@ ID,NAME,DOB,USERNAME,NOTES -1,Job Bloggs,1999-04-23,job-bloggs, -2,Terrance Bloggs,17/02/94,, +1,Job Bloggs ,1999-04-23,job-bloggs, +2,Terrance Bloggs,17/02/94, , 2,Terrance Bloggs,1994-02-17,terrance-bloggs,notes 3,Henry Bloggs,,henry-bloggs, \ No newline at end of file diff --git a/test/ValidateTests/Unit/RowValidatorTests.cs b/test/ValidateTests/Unit/RowValidatorTests.cs index 739516c..005df42 100644 --- a/test/ValidateTests/Unit/RowValidatorTests.cs +++ b/test/ValidateTests/Unit/RowValidatorTests.cs @@ -183,32 +183,36 @@ public void RowValidator_WhenValidatingMultipleRowsAndUnique_ErrorsDontStackUp() [TestMethod] public void RowValidator_WhenDataIsInvalid_PositionOfErrorIsProvided() { - const string ROW = @"nine,12/09/1999,,far too long"; + const string ROW = @"nine,12/09/1999,,far too long, "; const int ERROR_ONE = 1; const int ERROR_TWO = 6; const int ERROR_THREE = 17; - const int ERROR_FOUR = 18; + const int ERROR_FOUR = 18; + const int ERROR_FIVE = 31; - RowValidationError error = null; + RowValidationError error = null; _validator.AddColumnValidator(1, new NumberValidator()); _validator.AddColumnValidator(2, new TextFormatValidator(@"^\d\d\d\d-\d\d-\d\d$")); _validator.AddColumnValidator(3, new NotNullableValidator()); _validator.AddColumnValidator(4, new StringLengthValidator(6)); + _validator.AddColumnValidator(5, new NotNullableValidator(), trim: true); - _validator.IsValid(ROW); + _validator.IsValid(ROW); error = _validator.GetError(); Assert.AreEqual(ERROR_ONE, error.Errors[0].AtCharacter); Assert.AreEqual(ERROR_TWO, error.Errors[1].AtCharacter); Assert.AreEqual(ERROR_THREE, error.Errors[2].AtCharacter); - Assert.AreEqual(ERROR_FOUR, error.Errors[3].AtCharacter); - } + Assert.AreEqual(ERROR_FOUR, error.Errors[3].AtCharacter); + Assert.AreEqual(ERROR_FIVE, error.Errors[4].AtCharacter); + } [TestMethod] public void RowValidator_WhenDataIsInvalid_ColumnNumbersAreProvided() { - const string ROW = @"nine,12/09/1999,,far too long"; + const string ROW = @"nine,12/09/1999,,far too long, short enough "; + const int ERROR_COUNT = 4; const int ERROR_ONE = 1; const int ERROR_TWO = 2; const int ERROR_THREE = 3; @@ -219,11 +223,13 @@ public void RowValidator_WhenDataIsInvalid_ColumnNumbersAreProvided() _validator.AddColumnValidator(1, new NumberValidator()); _validator.AddColumnValidator(2, new TextFormatValidator(@"^\d\d\d\d-\d\d-\d\d$")); _validator.AddColumnValidator(3, new NotNullableValidator()); - _validator.AddColumnValidator(4, new StringLengthValidator(6)); + _validator.AddColumnValidator(4, new StringLengthValidator(6)); + _validator.AddColumnValidator(5, new StringLengthValidator(12), trim: true); - _validator.IsValid(ROW); + _validator.IsValid(ROW); error = _validator.GetError(); + Assert.AreEqual(ERROR_COUNT, error.Errors.Count); Assert.AreEqual(ERROR_ONE, error.Errors[0].Column); Assert.AreEqual(ERROR_TWO, error.Errors[1].Column); Assert.AreEqual(ERROR_THREE, error.Errors[2].Column);