Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/make properties selectable #8

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions CsvPortable/CsvPortable.Tests/PropertySelectionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
namespace CsvPortable.Tests;

using System.Globalization;
using Attributes;
using Configuration;
using Interfaces;

public class PropertySelectionTest
{
[Theory]
[InlineData(null)]
[InlineData(PropertyMode.Explicit)]
[InlineData(PropertyMode.All)]
public void PropertySelectionModeInParameter(PropertyMode? mode)
{
void AssertParameter(CsvParameter parameter, PropertyMode? expectedMode)
{
Assert.Equal(expectedMode, parameter.PropertyMode);
}

AssertParameter(new CsvParameter(propertyMode: mode), mode ?? CsvParameter.DefaultPropertyMode);
}


[Theory]
[InlineData(PropertyMode.All)]
[InlineData(PropertyMode.Explicit)]
public void ImportExportDataPropertyMode(PropertyMode mode)
{
var objectToExport = new PropertySelectionSpecifiedTestDto()
{
Property1 = 100,
Property2 = "SomethingElse",
Property3 = true,
Property4 = DateTime.Parse("1999.12.12")
};

CsvParameter parameter = new CsvParameter(propertyMode: mode);


void AssertExportedString(string definition, string expectedString, bool shouldBeContained = true)
{
if (shouldBeContained)
{
Assert.Contains(expectedString, definition);
}
else
{
Assert.DoesNotContain(expectedString, definition);
}
}

// Assert Definition.
// Property1 and Property3 should be always in the definition.
// Property2 and Property4 should be in the definition only if mode is All.

AssertExportedString(
ICsvPortable.ExportDefinition<PropertySelectionSpecifiedTestDto>(parameter),
nameof(PropertySelectionSpecifiedTestDto.Property1));


AssertExportedString(
ICsvPortable.ExportDefinition<PropertySelectionSpecifiedTestDto>(parameter),
nameof(PropertySelectionSpecifiedTestDto.Property2),
mode == PropertyMode.All);

AssertExportedString(
ICsvPortable.ExportDefinition<PropertySelectionSpecifiedTestDto>(parameter),
nameof(PropertySelectionSpecifiedTestDto.Property3));

AssertExportedString(
ICsvPortable.ExportDefinition<PropertySelectionSpecifiedTestDto>(parameter),
nameof(PropertySelectionSpecifiedTestDto.Property4),
mode == PropertyMode.All);

// Assert Exported csv string.
// Property1 and Property3 values should be always exported.
// Property2 and Property4 should be exported only if mode is All.

AssertExportedString(
ICsvPortable.ExportToCsvLine(objectToExport, parameter),
objectToExport.Property1.ToString());


AssertExportedString(
ICsvPortable.ExportToCsvLine(objectToExport, parameter),
objectToExport.Property2,
mode == PropertyMode.All);

AssertExportedString(
ICsvPortable.ExportToCsvLine(objectToExport, parameter),
objectToExport.Property3.ToString());

AssertExportedString(
ICsvPortable.ExportToCsvLine(objectToExport, parameter),
objectToExport.Property4.ToString(CultureInfo.CurrentCulture),
mode == PropertyMode.All);

// Assert imported values
// Property1 and Property3 values should be always be imported again.
// Property2 and Property4 should be imported only if mode is All, if not the values should be the defaults.
Assert.Equal(objectToExport.Property1, ICsvPortable.FromCsvRow<PropertySelectionSpecifiedTestDto>(
ICsvPortable.ExportToCsvLine(objectToExport, parameter), parameter).Property1);

Assert.Equal(mode == PropertyMode.All ? objectToExport.Property2 : PropertySelectionSpecifiedTestDto.DefaultProperty2, ICsvPortable.FromCsvRow<PropertySelectionSpecifiedTestDto>(
ICsvPortable.ExportToCsvLine(objectToExport, parameter), parameter).Property2);

Assert.Equal(objectToExport.Property3, ICsvPortable.FromCsvRow<PropertySelectionSpecifiedTestDto>(
ICsvPortable.ExportToCsvLine(objectToExport, parameter), parameter).Property3);

Assert.Equal(mode == PropertyMode.All ? objectToExport.Property4 : PropertySelectionSpecifiedTestDto.DefaultProperty4, ICsvPortable.FromCsvRow<PropertySelectionSpecifiedTestDto>(
ICsvPortable.ExportToCsvLine(objectToExport, parameter), parameter).Property4);
}

public record PropertySelectionSpecifiedTestDto
{
public const int DefaultProperty1 = -1;
public const string DefaultProperty2 = "default";
public const bool DefaultProperty3 = true;
public static readonly DateTime DefaultProperty4 = DateTime.Parse("2022.01.01");

[CsvProperty] public int Property1 { get; set; } = DefaultProperty1;

public string Property2 { get; set; } = DefaultProperty2;

[CsvProperty] public bool Property3 { get; set; } = DefaultProperty3;

public DateTime Property4 { get; set; } = DefaultProperty4;
}
}
155 changes: 71 additions & 84 deletions CsvPortable/CsvPortable/Configuration/CsvParameter.cs
Original file line number Diff line number Diff line change
@@ -1,89 +1,76 @@

using CsvPortable.Interfaces;

namespace CsvPortable.Configuration
{
public class CsvParameter
{
public static CsvParameter Default {get => (null, ";");}
public CsvParameter(CsvConfiguration? configuration)
{
Configuration = configuration;
}

public CsvParameter(CsvConfiguration? configuration, CsvDelimiter delimiter) : this(configuration)
{
Delimiter = delimiter ?? throw new ArgumentNullException(nameof(delimiter));
}

public CsvParameter(CsvConfiguration? configuration, CsvDelimiter delimiter, bool closeEnd) : this(configuration, delimiter)
{
CloseEnd = closeEnd;
}

public CsvParameter(CsvConfiguration? configuration, CsvDelimiter delimiter, bool closeEnd, List<(Type, CsvConfiguration)> specifiedConfigurations) : this(configuration, delimiter, closeEnd)
{
SpecifiedConfigurations = specifiedConfigurations ?? throw new ArgumentNullException(nameof(specifiedConfigurations));
}

public CsvParameter(CsvConfiguration? configuration, CsvDelimiter delimiter, bool closeEnd, params (Type, CsvConfiguration)[] specifiedConfigurations) : this(configuration, delimiter, closeEnd)
{
SpecifiedConfigurations = specifiedConfigurations.ToList();
}



/// <summary>
/// Gets or Sets Configuration for the Type.
/// </summary>
public CsvConfiguration? Configuration { get; set; } = null;

/// <summary>
/// Gets or Sets Delimiter --> default ";"
/// </summary>
public CsvDelimiter Delimiter { get; set; } = ";";

/// <summary>
/// Gets or Sets CloseEnd (The CSVLine gets closed(\r\n)) --> default "true"
/// </summary>
public bool CloseEnd { get; set; } = true;


public CsvParameter ParameterToUse(Type type, bool closeEnd)
{
bool MatchType((Type Type, CsvConfiguration Configuration) t)
{
return t.Type == type;
}

var configToUse = this.SpecifiedConfigurations.Exists(MatchType)
? this.SpecifiedConfigurations.FirstOrDefault(MatchType).Configuration
: this.Configuration;

return new CsvParameter(configToUse, this.Delimiter, closeEnd, this.SpecifiedConfigurations);
}
/// <summary>
/// Gets or Sets Specified Configurations.
/// For Class X use that Specification.
/// </summary>
public List<(Type Type, CsvConfiguration Configuration)> SpecifiedConfigurations { get; set; } = new List<(Type Type, CsvConfiguration Configuration)>();

public static implicit operator CsvParameter((CsvConfiguration? Configuration, CsvDelimiter Delimiter) tupel)
{
return new CsvParameter(tupel.Configuration, tupel.Delimiter);
}

public static implicit operator CsvParameter((CsvConfiguration? Configuration, CsvDelimiter Delimiter, bool CloseEnd) tupel)
{
return new CsvParameter(tupel.Configuration, tupel.Delimiter, tupel.CloseEnd);
}

public static implicit operator CsvParameter((CsvConfiguration Configuration, CsvDelimiter Delimiter, bool CloseEnd, List<(Type, CsvConfiguration)> SpecifiedConfigurations) tupel)
{
return new CsvParameter(tupel.Configuration, tupel.Delimiter, tupel.CloseEnd, tupel.SpecifiedConfigurations);
}



}
public class CsvParameter
{
public static readonly CsvConfiguration? DefaultConfiguration = null;
public static readonly CsvDelimiter DefaultDelimiter = ";";
public static readonly bool DefaultCloseEnd = true;
public static readonly PropertyMode DefaultPropertyMode = PropertyMode.All;
public static readonly List<(Type, CsvConfiguration)> DefaultSpecifiedConfigurations = new List<(Type, CsvConfiguration)>();

public static CsvParameter Default
{
get => (DefaultConfiguration, DefaultDelimiter);
}

public CsvParameter(CsvConfiguration? configuration = null, CsvDelimiter? delimiter = null, bool? closeEnd = null, PropertyMode? propertyMode = null, List<(Type Type, CsvConfiguration Configuration)>? specifiedConfigurations = null)
{
this.Configuration = configuration ?? DefaultConfiguration;
this.Delimiter = delimiter ?? DefaultDelimiter;
this.CloseEnd = closeEnd ?? DefaultCloseEnd;
this.PropertyMode = propertyMode ?? DefaultPropertyMode;
this.SpecifiedConfigurations = specifiedConfigurations ?? DefaultSpecifiedConfigurations;
}


/// <summary>
/// Gets or Sets Configuration for the Type.
/// </summary>
public CsvConfiguration? Configuration { get; set; }

/// <summary>
/// Gets or Sets Delimiter --> default ";"
/// </summary>
public CsvDelimiter Delimiter { get; set; }

/// <summary>
/// Gets or Sets CloseEnd (The CSVLine gets closed(\r\n)) --> default "true"
/// </summary>
public bool CloseEnd { get; set; }

public PropertyMode PropertyMode { get; set; }


public CsvParameter ParameterToUse(Type type, bool closeEnd)
{
bool MatchType((Type Type, CsvConfiguration Configuration) t)
{
return t.Type == type;
}

var configToUse = this.SpecifiedConfigurations.Exists(MatchType)
? this.SpecifiedConfigurations.FirstOrDefault(MatchType).Configuration
: this.Configuration;

return new CsvParameter(configToUse, this.Delimiter, closeEnd, this.PropertyMode, this.SpecifiedConfigurations);
}

/// <summary>
/// Gets or Sets Specified Configurations.
/// For Class X use that Specification.
/// </summary>
public List<(Type Type, CsvConfiguration Configuration)> SpecifiedConfigurations { get; set; }

public static implicit operator CsvParameter((CsvConfiguration? Configuration, CsvDelimiter Delimiter) tupel)
{
return new CsvParameter(tupel.Configuration, tupel.Delimiter);
}

public static implicit operator CsvParameter((CsvConfiguration? Configuration, CsvDelimiter Delimiter, bool CloseEnd) tupel)
{
return new CsvParameter(tupel.Configuration, tupel.Delimiter, tupel.CloseEnd);
}
}
}
7 changes: 7 additions & 0 deletions CsvPortable/CsvPortable/Configuration/PropertyMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CsvPortable.Configuration;

public enum PropertyMode
{
Explicit,
All
}
Loading
Loading