Skip to content

Commit

Permalink
Merge pull request #1 from NinjaRocks/engine_refactor
Browse files Browse the repository at this point in the history
- Refactor engine to align single and multi format parsers
  • Loading branch information
NinjaRocks authored Sep 5, 2019
2 parents 0988d44 + bd03ad3 commit 9a93d0e
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 154 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ FileLine base class has an index property that holds the index of the parsed lin
Once you have created the line class it is as simple as calling the Engine.GetFile() method as follows

>
`var files = new Engine<Employee>(configSettings).GetFiles();`
`var files = new Engine(configSettings).GetFiles<Employee>();`
The engine will parse the files found at the specified folder location and return a collection of
`File<Employee>` objects ie. one for each file parsed with an array of strongly typed lines (in this case Employee[]).
Expand Down Expand Up @@ -188,7 +188,7 @@ ie one for the header, footer and data line respectively.

We continue by creating two extra classes HeaderLine and FooterLine as follows.

public class HeaderLine : FileLine
public class Header : FileLine
{
[Column(0)]
public string Name { get; set; }
Expand All @@ -205,9 +205,9 @@ We continue by creating two extra classes HeaderLine and FooterLine as follows.

To parse the file you call the GetFiles() Method as follows -
>
`var files = new Engine<HeaderLine, Employee, Footer>(configSettings).GetFiles();`
`var files = new Engine(configSettings).GetFiles<Header, Employee, Footer>();`
The engine will parse the files and return a collection of `File<HeaderLine, Employee, Footer>` objects
The engine will parse the files and return a collection of `File<Header, Employee, Footer>` objects
ie. one for each file parsed with strongly typed header, footer and data line arrays.


Expand Down Expand Up @@ -243,9 +243,9 @@ An example dummy implementation is as follows

You can pass the custom provider to the engine as follows -

`var files = new Engine<Employee>(configSettings, new CustomProvider()).GetFiles();`
`var files = new Engine(configSettings, new CustomProvider()).GetFiles<Employee>();`

`var files = new Engine<HeaderLine, Employee, Footer>(configSettings, new CustomProvider()).GetFiles();`
`var files = new Engine(configSettings, new CustomProvider()).GetFiles<Header, Employee, Footer>();`

Returns
```
Expand All @@ -258,15 +258,15 @@ public class File<TH, TD, TF>
/// <summary>
/// Parsed header lines.
/// </summary>
public TH[] Headers { get; set; }
public TH Header { get; set; }
/// <summary>
/// Parsed data lines.
/// </summary>
public TD[] Data { get; set; }
/// <summary>
/// Parsed footer lines.
/// Parsed footer line.
/// </summary>
public TF[] Footers { get; set; }
public TF Footer { get; set; }
}
```

Expand Down
107 changes: 40 additions & 67 deletions src/Ninja.FileUtil/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,43 @@

namespace Ninja.FileUtil
{
public class Engine<T> where T : FileLine, new()
public class Engine
{
private readonly IFileProvider fileProvider;
private readonly ILineParser lineParser;

internal Engine(IFileProvider fileProvider, ILineParser lineParser)
internal Engine(ILineParser lineParser, IFileProvider fileProvider)
{
this.fileProvider = fileProvider;
this.lineParser = lineParser;
}

/// <summary>
/// Create Single line type Engine instance with default parser.
/// Create Engine instance with default parser and file provider.
/// </summary>
/// <param name="parserSettings">Parser setting instance.</param>
/// <param name="fileProvider">File provider instance.</param>
public Engine(IParserSettings parserSettings, IFileProvider fileProvider)
: this(fileProvider, new LineParser(parserSettings.Delimiter))
/// <remarks>
/// You need to provide the parser and file provider settings.
/// </remarks>
/// <param name="settings">Configuration settings for default file provider and parser</param>
public Engine(IConfigSettings settings)
: this(new LineParser(settings.ParserSettings), new DefaulProvider(settings.ProviderSettings, new FileHelper()))
{

}

/// <summary>
/// Create Multi line type Engine instance with default parser and default file provider.
/// Create Engine instance with custom file provider and default parser.
/// </summary>
/// <param name="settings">Configuration settings for default file provider and default parser</param>
public Engine(IConfigSettings settings)
: this(settings.ParserSettings, new DefaulProvider(settings.ProviderSettings, new FileHelper()))
/// <param name="parserSettings">Parser settings.</param>
/// <param name="fileProvider">Custom file provider instance.</param>
public Engine(IParserSettings parserSettings, IFileProvider fileProvider)
: this(new LineParser(parserSettings), fileProvider)
{

}

/// <summary>
/// Get all single fixed format lines from a text file parsed into a strongly typed array
/// Default delimiter is '|'
/// Default delimiter is '|'. Override by specifying the delimiter in parser settings.
/// Example File -
/// "John Walsh|456RT4|True|Male"
/// "Simone Walsh|456RT5|True|Female"
Expand All @@ -48,64 +52,30 @@ public Engine(IConfigSettings settings)
/// <returns>
/// Collection of Files each parsed with typed class arrays
/// </returns>
public File<T>[] GetFiles()
public File<T>[] GetFiles<T>() where T : FileLine, new()
{
var files = fileProvider.GetFiles();
return files.Select(file => new File<T>
{
FileMeta = new FileMeta
{
FileName = file.FileName,
FilePath = file.FilePath,
FileSize = file.FileSize,
Lines = file.Lines,
},
Data = lineParser.ParseWithNoLineType<T>(file.Lines)
})
.ToArray();
}
}

public class Engine<TH, TD, TF> where TH : FileLine, new()
where TD : FileLine, new()
where TF : FileLine, new()
{
private readonly IFileProvider fileProvider;
private readonly ILineParser lineParser;
private readonly IParserSettings parserSettings;

internal Engine(IFileProvider fileProvider, ILineParser lineParser)
{
this.fileProvider = fileProvider;
this.lineParser = lineParser;
}
/// <summary>
/// Create Multi line type Engine instance with default parser.
/// </summary>
/// <param name="parserSettings">Parser setting instance.</param>
/// <param name="fileProvider">File provider instance.</param>
public Engine(IParserSettings parserSettings, IFileProvider fileProvider)
: this(fileProvider, new LineParser(parserSettings.Delimiter))
{
this.parserSettings = parserSettings;
}

/// <summary>
/// Create Multi line type Engine instance with default parser and default file provider.
/// </summary>
/// <param name="settings">Configuration settings for default file provider and default parser</param>
public Engine(IConfigSettings settings)
: this(settings.ParserSettings, new DefaulProvider(settings.ProviderSettings, new FileHelper()))
{
FileMeta = new FileMeta
{
FileName = file.FileName,
FilePath = file.FilePath,
FileSize = file.FileSize,
Lines = file.Lines,
},
Data = lineParser.Parse<T>(file.Lines)
})
.ToArray();
}

/// <summary>
/// Get all multi-format lines from a text file parsed into header, data and footer
/// typed arrays respectively.
/// Header line starts with H, data line starts with D and
/// footer line starts with F by defaults
/// Default delimiter is '|'.
/// By default, Header line starts with H, data line starts with D and footer line starts with F.
/// Override these values in parser settings.
/// Example File -
/// "H|22-10-2016|Employee Status"
/// "D|John Walsh|456RT4|True"
Expand All @@ -118,8 +88,11 @@ public Engine(IConfigSettings settings)
/// <returns>
/// Collection of Files each parsed with header, footer and data typed arrays
/// </returns>
public File<TH, TD, TF>[] GetFiles()
{
public File<TH, TD, TF>[] GetFiles<TH,TD,TF>()
where TH : FileLine, new()
where TD : FileLine, new()
where TF : FileLine, new()
{
var files = fileProvider.GetFiles();

return files.Select(file =>
Expand All @@ -134,9 +107,9 @@ public File<TH, TD, TF>[] GetFiles()
Lines = file.Lines,
},
Headers = lineParser.ParseWithLineType<TH>(file.Lines.Where(x => x.StartsWith(parserSettings.LineHeaders.GetHeaderValue())).ToArray(), LineType.Header),
Footers = lineParser.ParseWithLineType<TF>(file.Lines.Where(x => x.StartsWith(parserSettings.LineHeaders.GetFooterValue())).ToArray(), LineType.Footer),
Data = lineParser.ParseWithLineType<TD>(file.Lines.Where(x => x.StartsWith(parserSettings.LineHeaders.GetDataValue())).ToArray(), LineType.Data)
Header = lineParser.Parse<TH>(file.Lines, LineType.Header).FirstOrDefault(),
Footer = lineParser.Parse<TF>(file.Lines, LineType.Footer).FirstOrDefault(),
Data = lineParser.Parse<TD>(file.Lines, LineType.Data)
};
return parsed;
Expand Down
8 changes: 4 additions & 4 deletions src/Ninja.FileUtil/File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ public class File<T> where T: FileLine
/// </summary>
public FileMeta FileMeta { get; set; }
/// <summary>
/// Parsed header lines.
/// Parsed header line.
/// </summary>
public TH[] Headers { get; set; }
public TH Header { get; set; }
/// <summary>
/// Parsed data lines.
/// </summary>
public TD[] Data { get; set; }
/// <summary>
/// Parsed footer lines.
/// Parsed footer line.
/// </summary>
public TF[] Footers { get; set; }
public TF Footer { get; set; }
}

public class FileMeta
Expand Down
4 changes: 2 additions & 2 deletions src/Ninja.FileUtil/Ninja.FileUtil.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RepositoryType>Public</RepositoryType>
Expand All @@ -16,6 +16,6 @@ Example: pipe delimited, csv, etc.</Description>
<Product>Fixed Width File Parser</Product>
<PackageProjectUrl>https://github.com/NinjaRocks/FileUtil.Core</PackageProjectUrl>
<PackageIconUrl>https://1drv.ms/u/s!Aq_ncig7TU4551b5fzxOad-pDMfL</PackageIconUrl>
<Version>1.0.4</Version>
<Version>1.1.0</Version>
</PropertyGroup>
</Project>
20 changes: 10 additions & 10 deletions src/Ninja.FileUtil/Parser/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ public static char GetValue(this IDelimiter delimiter)
return delimiter?.Value ?? ',';
}

public static string GetHeaderValue(this ILineHeaders lineHeaders)
public static string GetLineHead(this ILineHeaders lineHeaders, LineType type)
{
return lineHeaders?.Header ?? "H";
}
public static string GetFooterValue(this ILineHeaders lineHeaders)
{
return lineHeaders?.Footer ?? "F";
}
public static string GetDataValue(this ILineHeaders lineHeaders)
{
return lineHeaders?.Data ?? "D";
switch (type)
{
case LineType.Header:
return lineHeaders?.Header ?? "H";
case LineType.Footer:
return lineHeaders?.Footer ?? "F";
default:
return lineHeaders?.Data ?? "D";
}
}
}
}
5 changes: 2 additions & 3 deletions src/Ninja.FileUtil/Parser/ILineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ namespace Ninja.FileUtil.Parser
{
internal interface ILineParser
{
T[] ParseWithNoLineType<T>(string[] lines) where T : IFileLine, new();
T[] ParseWithLineType<T>(string[] lines, LineType type) where T : IFileLine, new();
T[] Parse<T>(string[] lines) where T : IFileLine, new();
T[] Parse<T>(string[] lines, LineType type) where T : IFileLine, new();
}

}
20 changes: 10 additions & 10 deletions src/Ninja.FileUtil/Parser/Impl/LineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@
using System.Threading.Tasks;
using Ninja.FileUtil.Configuration;


namespace Ninja.FileUtil.Parser.Impl
{
internal class LineParser : ILineParser
{
private readonly IDelimiter delimiter;
private readonly IParserSettings parserSettings;

public LineParser(IDelimiter delimiter)
public LineParser(IParserSettings parserSettings)
{
this.delimiter = delimiter;
this.parserSettings = parserSettings;
}

public T[] ParseWithNoLineType<T>(string[] lines) where T : IFileLine, new()
public T[] Parse<T>(string[] lines) where T : IFileLine, new()
{
return Parse<T>(lines, LineType.Data, false);

}

public T[] ParseWithLineType<T>(string[] lines, LineType type) where T : IFileLine, new()
public T[] Parse<T>(string[] lines, LineType type) where T : IFileLine, new()
{
return Parse<T>(lines, type, true);
var filteredLines = lines?.Where(x => x.StartsWith(parserSettings.LineHeaders.GetLineHead(type))).ToArray();
return Parse<T>(filteredLines, type, true);
}

private T[] Parse<T>(string[] lines, LineType type, bool hasLineHeader) where T : IFileLine, new()
{

if (lines == null || lines.Length == 0) return Enumerable.Empty<T>().ToArray();
if (lines == null || lines.Length == 0)
return Enumerable.Empty<T>().ToArray();

var list = new T[lines.Length];

Expand Down Expand Up @@ -147,7 +147,7 @@ public LineParser(IDelimiter delimiter)

private string[] GetDelimiterSeparatedValues(string line)
{
var values = line.Split(delimiter.GetValue())
var values = line.Split(parserSettings.Delimiter.GetValue())
.Select(x => !string.IsNullOrWhiteSpace(x)? x.Trim(): x)
.ToArray();
return values;
Expand Down
Loading

0 comments on commit 9a93d0e

Please sign in to comment.