Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Px.Utils.ModelBuilders;
using Px.Utils.ModelBuilders;
using Px.Utils.Models.Metadata.Enums;
using Px.Utils.PxFile;
using System.Globalization;

namespace ModelBuilderTests.ValueParserUtilitiesTests
namespace Px.Utils.UnitTests.ModelBuilderTests.ValueParserUtilitiesTests
{
[TestClass]
public class StringToDimensionTypeTests
Expand All @@ -16,14 +18,27 @@ public void TimeTest()
}

[TestMethod]
public void ContentTest()
public void ContentsTest()
{
string input = "Content";
string input = "Contents";
DimensionType expected = DimensionType.Content;
DimensionType actual = ValueParserUtilities.StringToDimensionType(input);
Assert.AreEqual(expected, actual);
}

[TestMethod]
[DataRow("RANKING", DimensionType.Ordinal)]
[DataRow("region", DimensionType.Geographical)]
public void CustomAliasTest(string alias, DimensionType expected)
{
string input = alias.ToUpper(CultureInfo.InvariantCulture); // Testing case-insensitivity
PxFileConfiguration conf = PxFileConfiguration.Default;
conf.Tokens.VariableTypes.Mappings[alias] = expected;

DimensionType actual = ValueParserUtilities.StringToDimensionType(input, conf);
Assert.AreEqual(expected, actual);
}

[TestMethod]
public void DefaultValueTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
using Px.Utils.Validation;
using Px.Utils.Validation.ContentValidation;
using Px.Utils.Validation.SyntaxValidation;
using Px.Utils.PxFile;
using Px.Utils.Models.Metadata.Enums;
using System.Text;
using System.Reflection;
using System.Globalization;

namespace Px.Utils.UnitTests.Validation.ContentValidationTests
{
Expand Down Expand Up @@ -536,6 +539,60 @@ public void ValidateValueTypesCalledWithStructuredEntryArrayWithWrongValuesRetur
}
}

[TestMethod]
[DataRow("ranking", DimensionType.Ordinal)]
[DataRow("REGION", DimensionType.Geographical)]
public void ValidateValueContentsCalledWithCustomDimensionTypesValueReturnsWithoutFeedback(string alias, DimensionType dimensionType)
{
// Arrange
PxFileConfiguration conf = PxFileConfiguration.Default;
conf.Tokens.VariableTypes.Mappings[alias] = dimensionType;

ValidationStructuredEntry entry = new(
filename,
new ValidationStructuredEntryKey("VARIABLE-TYPE", "fi", "foo"),
alias.ToUpper(CultureInfo.InvariantCulture), // The value is converted to upper case to verify case insensitivity of the dimension type matching
0,
[],
0,
Utils.Validation.ValueType.StringValue);

ContentValidator validator = new(filename, encoding, [entry], conf: conf);

// Act
ValidationFeedback? result = ContentValidator.ValidateValueContents(entry, validator);

// Assert
Assert.IsNull(result);
}

[TestMethod]
public void ValidateValueContentsCalledWithUnknownDimensionTypeValueReturnsWithError()
{
// Arrange
PxFileConfiguration conf = PxFileConfiguration.Default;

ValidationStructuredEntry entry = new(
filename,
new ValidationStructuredEntryKey("VARIABLE-TYPE", "fi", "foo"),
"Ranking",
0,
[],
0,
Utils.Validation.ValueType.StringValue);

ContentValidator validator = new(filename, encoding, [entry], conf: conf);

// Act
ValidationFeedback? result = ContentValidator.ValidateValueContents(entry, validator);

// Assert
Assert.IsNotNull(result);
Assert.HasCount(1, result);
Assert.AreEqual(ValidationFeedbackRule.InvalidValueFound, result.First().Key.Rule);
Assert.AreEqual(ValidationFeedbackLevel.Error, result.First().Key.Level);
}

[TestMethod]
public void ValidateValueAmountsCalledWithUnmatchingAmountOfElementsReturnsWithError()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public async Task ValidateDatabasAsynceWithCustomFunctionsReturnsFeedback()
IDatabaseValidator[] customValidators =
[
new MockCustomDatabaseValidator()
];
];
DatabaseValidator validator = new(
"database_invalid",
customPxFileValidators: customValidators,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ internal static class ContentValidationFixtures
private static readonly ValidationStructuredEntry variableTypeBarEntry =
new(filename,
new ValidationStructuredEntryKey("VARIABLE-TYPE", null, "bar"),
"Content",
"Contents",
23,
[],
13,
Expand Down
10 changes: 5 additions & 5 deletions Px.Utils.UnitTests/Validation/Fixtures/PxFileFixtures.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Px.Utils.UnitTests.Validation.Fixtures
namespace Px.Utils.UnitTests.Validation.Fixtures
{
internal static class PxFileFixtures
{
Expand All @@ -22,7 +22,7 @@ internal static class PxFileFixtures
"\r\nCODES(\"Vuosi\")=\"2015\",\"2016\",\"2017\",\"2018\",\"2019\",\"2020\",\"2021\",\"2022\",\"2023\",\"2024\";" +
"\r\nCODES(\"Tiedot\")=\"code-foo-val-a\",\"code-foo-val-b\";" +
"\r\nVARIABLE-TYPE(\"Vuosi\")=\"Time\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Content\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Contents\";" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-a\")=1;" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-b\")=1;" +
"\r\nLAST-UPDATED(\"Tiedot\",\"foo-val-a\")=\"20231101 08:00\";" +
Expand Down Expand Up @@ -64,7 +64,7 @@ internal static class PxFileFixtures
"\r\nCODES(\"Vuosi\")=\"2015\",\"2016\",\"2017\",\"2018\",\"2019\",\"2020\",\"2021\",\"2022\",\"2023\",\"2024\";" +
"\r\nCODES(\"Tiedot\")=\"code-foo-val-a\",\"code-foo-val-b\";" +
"\r\nVARIABLE-TYPE(\"Vuosi\")=\"Time\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Content\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Contents\";" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-a\")=1;" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-b\")=1;" +
"\r\nLAST-UPDATED(\"Tiedot\",\"foo-val-a\")=\"20231101 08:00\";" +
Expand Down Expand Up @@ -94,7 +94,7 @@ internal static class PxFileFixtures
"\r\nCODES(\"Vuosi\")=\"2015\",\"2016\",\"2017\",\"2018\",\"2019\",\"2020\",\"2021\",\"2022\",\"2023\",\"2024\";" +
"\r\nCODES(\"Tiedot\")=\"code-foo-val-a\",\"code-foo-val-b\";" +
"\r\nVARIABLE-TYPE(\"Vuosi\")=\"Time\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Content\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Contents\";" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-a\")=1;" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-b\")=1;" +
"\r\nLAST-UPDATED(\"Tiedot\",\"foo-val-a\")=\"20231101 08:00\";" +
Expand Down Expand Up @@ -135,7 +135,7 @@ internal static class PxFileFixtures
"\r\nCODES(\"Vuosi\")=\"2015\",\"2016\",\"2017\",\"2018\",\"2019\",\"2020\",\"2021\",\"2022\",\"2023\",\"2024\";" +
"\r\nCODES(\"Tiedot\")=\"code-foo-val-a\",\"code-foo-val-b\";" +
"\r\nVARIABLE-TYPE(\"Vuosi\")=\"Time\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Content\";" +
"\r\nVARIABLE-TYPE(\"Tiedot\")=\"Contents\";" +
"\r\nPRECISION(\"Tiedot\",\"foo-val-a\")=1;" +
"\r\nLAST-UPDATED(\"Tiedot\",\"foo-val-a\")=\"20231101 08:00\";" +
"\r\nUNITS(\"Tiedot\",\"foo-val-a\")=\"kpl\";" +
Expand Down
13 changes: 13 additions & 0 deletions Px.Utils.sln
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Px.Utils.TestingApp", "Px.U
{D94934AF-6B41-4C66-818A-C4C33230E9DD} = {D94934AF-6B41-4C66-818A-C4C33230E9DD}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "architecture", "architecture", "{BFA8E05B-EBD8-4085-B765-EAED69DD0874}"
ProjectSection(SolutionItems) = preProject
docs\architecture.md = docs\architecture.md
docs\architecture.models.md = docs\architecture.models.md
docs\architecture.operations.md = docs\architecture.operations.md
docs\architecture.overview.md = docs\architecture.overview.md
docs\architecture.readers.md = docs\architecture.readers.md
docs\architecture.serializers.md = docs\architecture.serializers.md
docs\architecture.testing.md = docs\architecture.testing.md
docs\architecture.validation.md = docs\architecture.validation.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -60,6 +72,7 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EB4119B8-8292-418A-9CD3-2905DA67B889} = {BC1C9772-9B8F-49A7-A8F3-09E3A94789ED}
{BFA8E05B-EBD8-4085-B765-EAED69DD0874} = {42DFE3AF-7507-415A-806B-99B74519BF97}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B1F81A3B-9FF5-4557-8A5A-A9519C42C2B2}
Expand Down
22 changes: 9 additions & 13 deletions Px.Utils/ModelBuilders/ValueParserUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Px.Utils.Models.Metadata.Enums;
using Px.Utils.Models.Metadata.Enums;
using Px.Utils.Models.Metadata.ExtensionMethods;
using Px.Utils.PxFile;
using System.Globalization;

namespace Px.Utils.ModelBuilders
{
Expand Down Expand Up @@ -102,6 +103,7 @@ public static string GetTimeValValueRangeString(string input, PxFileConfiguratio
/// <summary>
/// Parses a string into a <see cref="DimensionType"/> enumeration value.
/// This method maps the input string to a <see cref="DimensionType"/> enumeration value based on the provided or default PxFileConfiguration configuration.
/// Mapping is done using the configured variable type mappings.
/// If the input string does not map to a known <see cref="DimensionType"/>, the method returns <see cref="DimensionType.Unknown"/>.
/// </summary>
/// <param name="input">The string to parse into a <see cref="DimensionType"/> enumeration value.</param>
Expand All @@ -110,20 +112,14 @@ public static string GetTimeValValueRangeString(string input, PxFileConfiguratio
public static DimensionType StringToDimensionType(string input, PxFileConfiguration? conf = null)
{
conf ??= PxFileConfiguration.Default;
Dictionary<string, DimensionType> map = new()
{
{conf.Tokens.VariableTypes.Content, DimensionType.Content},
{conf.Tokens.VariableTypes.Time, DimensionType.Time},
{conf.Tokens.VariableTypes.Ordinal, DimensionType.Ordinal},
{conf.Tokens.VariableTypes.Nominal, DimensionType.Nominal},
{conf.Tokens.VariableTypes.Geographical, DimensionType.Geographical},
{conf.Tokens.VariableTypes.Other, DimensionType.Other},
{conf.Tokens.VariableTypes.Unknown, DimensionType.Unknown}
};

string cleanString = input.CleanStringDelimeters(conf.Symbols.Value.StringDelimeter);
if (map.TryGetValue(cleanString, out DimensionType value)) return value;
else return DimensionType.Unknown;
if (conf.Tokens.VariableTypes.Mappings.TryGetValue(cleanString, out DimensionType value))
{
return value;
}

return DimensionType.Unknown;
}
}
}
2 changes: 1 addition & 1 deletion Px.Utils/Px.Utils.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<PackageId>Px.Utils</PackageId>
<Version>1.4.1</Version>
<Version>1.5.0</Version>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
37 changes: 19 additions & 18 deletions Px.Utils/PxFile/PxFileConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Px.Utils.Models.Metadata.Enums;
using Px.Utils.Models.Metadata.Enums;

namespace Px.Utils.PxFile
{
Expand Down Expand Up @@ -107,28 +107,29 @@ private TimeValue() { }
public static TimeValue DefaultTimeValue => new();
}

/// <summary>
/// Defines accepted tokens for parsing and validating dimension types using an expandable dictionary string to <see cref="DimensionType"/>.
/// </summary>
public class VariableTypeTokens
{
private const string CONTENT = "Content";
private const string TIME = "Time";
private const string ORDINAL = "Ordinal";
private const string NOMINAL = "Nominal";
private const string GEOGRAPHICAL = "Geographical";
private const string OTHER = "Other";
private const string UNKNOWN = "Unknown";
private const string CLASSIFICATORY = "Classificatory";

public string Content { get; set; } = CONTENT;
public string Time { get; set; } = TIME;
public string Ordinal { get; set; } = ORDINAL;
public string Nominal { get; set; } = NOMINAL;
public string Geographical { get; set; } = GEOGRAPHICAL;
public string Other { get; set; } = OTHER;
public string Unknown { get; set; } = UNKNOWN;
public string Classificatory { get; set; } = CLASSIFICATORY;
/// <summary>
/// Gets or sets the expandable dictionary mapping string tokens to dimension types.
/// </summary>
public Dictionary<string, DimensionType> Mappings { get; set; } = new(StringComparer.OrdinalIgnoreCase)
{
{ "Time", DimensionType.Time },
{ "Contents", DimensionType.Content },
{ "Geographical", DimensionType.Geographical },
{ "Ordinal", DimensionType.Ordinal },
{ "Nominal", DimensionType.Nominal },
{ "Other", DimensionType.Other },
};

private VariableTypeTokens() { }

/// <summary>
/// Gets the default variable type tokens configuration.
/// </summary>
public static VariableTypeTokens DefaultVariableTypeTokens => new();
}

Expand Down
Loading
Loading