Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
eramella committed Feb 25, 2018
0 parents commit 281b2af
Show file tree
Hide file tree
Showing 14 changed files with 950 additions and 0 deletions.
443 changes: 443 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/QFXparser.TestApp/bin/Debug/netcoreapp2.0/QFXparser.TestApp.dll",
"args": [],
"cwd": "${workspaceFolder}/QFXparser.TestApp",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"csharp.format.enable": false
}
15 changes: 15 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/QFXparser.TestApp/QFXparser.TestApp.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
46 changes: 46 additions & 0 deletions QFXparser.Core/Parser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace QFXparser.Core
{
public class Parser
{
public static IEnumerable<Token> Parse(string fileText)
{

Token token = new Token();

foreach (var character in fileText)
{
if (character == '<')
{
if (!token.IsElement)
{
if (!string.IsNullOrEmpty(token.Content))
{
yield return token;
}
token.ClearToken();
}

token.IsElement = true;
}
else if (character == '>')
{
if (!string.IsNullOrEmpty(token.Content))
{
yield return token;
}
token.ClearToken();
}
else
{
token.AddCharacter(character);
}
}
}
}
}
13 changes: 13 additions & 0 deletions QFXparser.Core/QFXparser.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Company>emaquest.net</Company>
<Product>QFXparser</Product>
<PackageId>QFXparser</PackageId>
<Authors>Emanuele Ramella-Paia</Authors>
<Description>Simple parser for .qfx and .qbo files.</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

</Project>
16 changes: 16 additions & 0 deletions QFXparser.Core/Statement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace QFXparser.Core
{
[NodeName("CCSTMTRS")]
public class Statement
{
[NodeName("ACCTID")]
public string AccountNum { get; set; }

[NodeName("BANKTRANLIST")]
public ICollection<Transaction> Transactions { get; set; } = new List<Transaction>();
}
}
170 changes: 170 additions & 0 deletions QFXparser.Core/StatementBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace QFXparser.Core
{
public class StatementBuilder
{
private Statement _statement;
private Transaction _currentTransaction;
private string _fileText;

public StatementBuilder(string fileNamePath)
{
using (StreamReader sr = new StreamReader(fileNamePath))
{
_fileText = sr.ReadToEnd();
}

}

public StatementBuilder(Stream fileStream)
{
using (StreamReader sr = new StreamReader(fileStream))
{
_fileText = sr.ReadToEnd();
}

}

public Statement Build()
{

MemberInfo currentMember = null;

foreach (var token in Parser.Parse(_fileText))
{
if (token.IsElement)
{
var result = GetPropertyInfo(token.Content);
if (result != null)
{
switch (result.Type)
{
case NodeType.StatementOpen:
_statement = new Statement();
break;
case NodeType.StatementClose:
return _statement;
break;
case NodeType.TransactionOpen:
_currentTransaction = new Transaction();
break;
case NodeType.TransactionClose:
_statement.Transactions.Add(_currentTransaction);
_currentTransaction = null;
break;
case NodeType.StatementProp:
case NodeType.TransactionProp:
currentMember = result.Member;
break;
default:
break;
}
}
else
{
currentMember = null;
}
}
else
{
if (currentMember != null && currentMember is PropertyInfo)
{
var property = (PropertyInfo)currentMember;
switch (property.DeclaringType.Name)
{
case "Statement":
property.SetValue(_statement, token.Content);
break;
case "Transaction":
property.SetValue(_currentTransaction, token.Content);
break;
default:
break;
}
}
}
}

return _statement;
}

private PropertyResult GetPropertyInfo(string token)
{
var propertyResult = new PropertyResult();

if (typeof(Statement).GetCustomAttribute<NodeNameAttribute>().CloseTag == token)
{
propertyResult.Member = typeof(Statement);
propertyResult.Type = NodeType.StatementClose;
return propertyResult;
}

if (typeof(Transaction).GetCustomAttribute<NodeNameAttribute>().CloseTag == token)
{
propertyResult.Member = typeof(Transaction);
propertyResult.Type = NodeType.TransactionClose;
return propertyResult;
}

if (typeof(Statement).GetCustomAttribute<NodeNameAttribute>().OpenTag == token)
{
propertyResult.Member = typeof(Statement);
propertyResult.Type = NodeType.StatementOpen;
return propertyResult;
}

if (typeof(Transaction).GetCustomAttribute<NodeNameAttribute>().OpenTag == token)
{
propertyResult.Member = typeof(Transaction);
propertyResult.Type = NodeType.TransactionOpen;
return propertyResult;
}


var statementMember = typeof(Statement).GetProperties().FirstOrDefault(m => m.GetCustomAttribute<NodeNameAttribute>().OpenTag == token);

if (statementMember != null)
{
propertyResult.Member = statementMember;
propertyResult.Type = NodeType.StatementProp;
return propertyResult;
}

var transactionMember = typeof(Transaction).GetProperties().Where(m => m.GetCustomAttribute<NodeNameAttribute>() != null)
.FirstOrDefault(m => m.GetCustomAttribute<NodeNameAttribute>().OpenTag == token);

if (transactionMember != null)
{
propertyResult.Member = transactionMember;
propertyResult.Type = NodeType.TransactionProp;
return propertyResult;
}

return null;

}

}

internal class PropertyResult
{
public MemberInfo Member { get; set; }
public NodeType Type { get; set; }
}

internal enum NodeType
{
StatementOpen,
StatementClose,
TransactionOpen,
TransactionClose,
StatementProp,
TransactionProp
}
}
37 changes: 37 additions & 0 deletions QFXparser.Core/Token.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace QFXparser.Core
{
public class Token
{
private StringBuilder _content;

public Token()
{
_content = new StringBuilder();
}

public bool IsElement { get; set; } = false;

public string Content
{
get
{
return _content.ToString().Trim();
}
}

public void AddCharacter(char character)
{
_content.Append(character);
}

public void ClearToken()
{
_content.Clear();
IsElement = false;
}
}
}
32 changes: 32 additions & 0 deletions QFXparser.Core/TokenNameAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;

namespace QFXparser.Core
{
internal class NodeNameAttribute : Attribute
{
private string _openTag;
private string _closeTag;

public NodeNameAttribute(string openTag, string closeTag = "")
{
_openTag = openTag;
_closeTag = closeTag;
}

public string OpenTag
{
get
{
return _openTag;
}
}

public string CloseTag
{
get
{
return _closeTag;
}
}
}
}
Loading

0 comments on commit 281b2af

Please sign in to comment.