// Copyright (C) Stichting Deltares 2018. All rights reserved.
//
// This file is part of the application DAM - Clients Library.
//
// DAM - UI is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Globalization;
using System.Reflection;
namespace Deltares.Dam.Data
{
public class CsvExporter
{
private const string NullValue = "NULL";
private const string Delimiter = ";";
private readonly string fileName;
private readonly IEnumerable data;
private string columnHeader;
private bool headerWritten;
public CsvExporter(string fileName, IEnumerable data)
{
this.data = data;
ThrowHelper.ThrowWhenConditionIsTrue(
StringResourceNames.OutputFileNameNotValid,
() => string.IsNullOrEmpty(fileName) || fileName.Trim() == "");
this.fileName = fileName;
headerWritten = false;
WriteHeaderInFirstLine = true;
}
public bool WriteHeaderInFirstLine { get; set; }
public void WriteFile()
{
using (TextWriter writer = new StreamWriter(this.fileName, false))
{
foreach (T dataItem in data)
{
string line = GetDataItemString(dataItem);
if (line.Trim() != "")
{
if (WriteHeaderInFirstLine && !headerWritten)
{
writer.WriteLine(columnHeader);
headerWritten = true;
}
writer.WriteLine(line);
}
else
{
writer.WriteLine("No (public) properties are annotated with the column meta data CsvColumnAttribute.");
}
}
}
}
private string GetDataItemString(T dataItem)
{
if (dataItem.Equals(default(T)))
throw new CsvExporterException("Invalid export data item");
var header = new Dictionary();
var table = new Dictionary();
string line = "";
foreach (var pInfo in (typeof(T).GetProperties()))
{
foreach (Attribute attribute in pInfo.GetCustomAttributes(true))
{
var attr = attribute as CsvExportColumnAttribute;
if (null != attr)
{
ThrowWhenIndexAlreadyExists(header, attr.Index, pInfo.Name);
header.Add(attr.Index, attr.Name);
object value;
try
{
value = pInfo.GetValue(dataItem, null) ?? NullValue;
}
catch (TargetInvocationException)
{
value = NullValue;
}
table.Add(attr.Index, value);
}
}
}
// assemble the data line
if (table.Count > 0)
{
// order the keys by column index
var keys = table.Keys.OrderBy(k => k);
var counter = 0;
foreach (var index in keys)
{
var val = string.Format(CultureInfo.InvariantCulture, "{0}", table[index]);
line += val + (++counter < table.Count ? Delimiter : "");
}
// assemble the column header
if (WriteHeaderInFirstLine && string.IsNullOrEmpty(columnHeader))
{
counter = 0;
foreach (var index in keys)
columnHeader += header[index] + (++counter < table.Count ? Delimiter : "");
}
}
return line;
}
private static void ThrowWhenIndexAlreadyExists(IDictionary dictionary, int index, string propertyName)
{
string message = string.Format(ThrowHelper.GetResourceString(StringResourceNames.CsvColumnIndexAlreadyExists), index, propertyName);
ThrowHelper.ThrowWhenConditionIsTrue(
message,
() => dictionary.ContainsKey(index));
}
}
}