Skip to content

Commit

Permalink
Implement output of the file
Browse files Browse the repository at this point in the history
  • Loading branch information
wgnf committed Oct 23, 2021
1 parent 8f9f4c3 commit 7937e06
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/CsvProc9000/Csv/CsvField.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CsvProc9000.Csv
{
public record CsvField(string FieldName, string Value);
public record CsvField(string Name, string Value);
}
51 changes: 49 additions & 2 deletions src/CsvProc9000/Csv/CsvFile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace CsvProc9000.Csv
Expand All @@ -10,10 +14,10 @@ public class CsvFile

public CsvFile([NotNull] string fileName)
{
FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
OriginalFileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
}

public string FileName { get; }
public string OriginalFileName { get; }

public IEnumerable<CsvRow> Rows => _rows;

Expand All @@ -23,5 +27,48 @@ public void AddRow([NotNull] CsvRow row)

_rows.Add(row);
}

public async Task SaveToAsync(
IFileSystem fileSystem,
string destinationFileName,
string delimiter)
{
var contentStringBuilder = new StringBuilder();

var fieldNames = Rows
.SelectMany(row => row.Fields)
.Select(field => field.Name)
.Distinct()
.ToList();

// add header row
contentStringBuilder.AppendJoin(delimiter, fieldNames);
contentStringBuilder.AppendLine();

foreach (var row in Rows)
{
var firstIteration = true;

foreach (var fieldName in fieldNames)
{
// append the delimiter to the previous field when get here not in the first iteration
if (firstIteration) firstIteration = false;
else contentStringBuilder.Append(delimiter);

var field = row.Fields.FirstOrDefault(f => f.Name == fieldName);
var fieldValue = string.Empty;

if (field != null)
fieldValue = field.Value;

contentStringBuilder.Append(fieldValue);
}

contentStringBuilder.AppendLine();
}

var content = contentStringBuilder.ToString();
await fileSystem.File.WriteAllTextAsync(destinationFileName, content);
}
}
}
5 changes: 4 additions & 1 deletion src/CsvProc9000/Options/CsvProcessorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ public class CsvProcessorOptions

[UsedImplicitly]
public string InboxDelimiter { get; set; }

[UsedImplicitly]
public bool DeleteInboxFile { get; set; } = true;

[UsedImplicitly]
public string Outbox { get; set; }

[UsedImplicitly]
public string OutboxDelimiter { get; set; }

[UsedImplicitly]
public List<Rule> Rules { get; set; }
}
Expand Down
42 changes: 29 additions & 13 deletions src/CsvProc9000/Processors/CsvProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
Expand Down Expand Up @@ -40,20 +40,14 @@ public async Task ProcessAsync(IFileInfo file)
await ProcessInternalAsync(file);
}

private bool CanProcess(IFileInfo file)
private bool CanProcess(IFileSystemInfo file)
{
if (!file.Exists)
{
_logger.LogDebug("Cannot process file {File}, because it does not exist", file.FullName);
return false;
}

if (file.IsReadOnly)
{
_logger.LogDebug("Cannot process file {File}, because it is read-only", file.FullName);
return false;
}

// ReSharper disable once InvertIf
if (!file.Extension.Equals(".csv"))
{
Expand All @@ -75,17 +69,39 @@ private async Task ProcessInternalAsync(IFileSystemInfo file)

_logger.LogDebug("Processor: Applying rules to file {File}...", file.FullName);
ApplyRulesToFile(csvFile);

await SaveResultAsync(file, csvFile);
}


// if (_fileSystem.Directory.Exists(_processorOptions.Outbox))
// _fileSystem.Directory.CreateDirectory(_processorOptions.Outbox);

private async Task SaveResultAsync(IFileSystemInfo file, CsvFile csvFile)
{
var fileName = file.Name;
var destinationFileName = _fileSystem.Path.Combine(_processorOptions.Outbox, fileName);

_logger.LogInformation("Processor: Saving result to {Destination}...", destinationFileName);

if (_fileSystem.Directory.Exists(_processorOptions.Outbox))
_fileSystem.Directory.CreateDirectory(_processorOptions.Outbox);

await csvFile.SaveToAsync(_fileSystem, destinationFileName, _processorOptions.OutboxDelimiter);

if (!file.Exists) return;
if (!_processorOptions.DeleteInboxFile) return;

_logger.LogDebug("Processor: Deleting original file {File} from Inbox {Inbox}...",
file.FullName, _processorOptions.Inbox);

_fileSystem.File.Delete(file.FullName);
}

private void ApplyRulesToFile(CsvFile csvFile)
{
if (_processorOptions.Rules == null || !_processorOptions.Rules.Any())
{
_logger.LogWarning("Processor: Cannot process file {File} because there are no rules defined",
csvFile.FileName);
csvFile.OriginalFileName);
return;
}

Expand All @@ -111,7 +127,7 @@ private void ApplyRuleToRow(CsvRow row, Rule rule, CsvFile file)
if (!MeetsRowConditions(row, rule, file)) return;

_logger.LogTrace("Processor: File {File} meets rule at index {RuleIndex}. Applying rule...",
file.FileName, _processorOptions.Rules.IndexOf(rule));
file.OriginalFileName, _processorOptions.Rules.IndexOf(rule));

foreach (var (columnName, fieldValue) in rule.Steps)
{
Expand All @@ -132,7 +148,7 @@ private bool MeetsRowConditions(CsvRow row, Rule rule, CsvFile file)
{
foreach (var condition in rule.Conditions)
{
var field = row.Fields.FirstOrDefault(field => field.FieldName == condition.Field);
var field = row.Fields.FirstOrDefault(field => field.Name == condition.Field);
if (field == null)
{
_logger.LogTrace(
Expand Down

0 comments on commit 7937e06

Please sign in to comment.