using System.Collections.Generic;
const bool FoceErrorWhenNotMatch = false;
public static void Main()
Match("73000-11043,13540,13708,14040,14110,14152,14205,14210,14238,14239,14291,14295,14296,14319,14325,14332,14333,14334,14432,14433,14469,14472,14538,14585,14586,14587,14588,14589,14612-*-*;155000-*-*-*;153000-*-*-*;10000-14179,14181,14208,14200,13655,14243-NL-AT,BE,BG,HR,CY,CZ,DK,EE,FI,FR,DE,GR,HU,IE,IM,IT,LV,LT,LU,MT,MC,NL,RO,SK,SI,SE;10000-14180,14183,14167,14211,14184,14253,14198,14207,14133-US-US;156000-*-*-*;157000-*-*-*;158000-*-*-*;",
new Data("156000", "14179", "NL", "UK", true),
new Data("157000", "14179", "NL", "UK", true),
new Data("158000", "14179", "NL", "UK", true),
new Data("56000", "14179", "NL", "UK", false),
new Data("57000", "14179", "NL", "UK", false),
new Data("58000", "14179", "NL", "UK", false),
forceErrorWhenNotMatch: FoceErrorWhenNotMatch);
public static void Match(string rule, IEnumerable<Data> dataSet, string name = default, bool forceErrorWhenNotMatch = false)
var r = new List<Data>();
foreach(var d in dataSet)
var (tenantId, locationId, origin, destination, expectedResult, _, _) = d;
var matchResult = rule.MatchSettingsRules(new List<string>{ tenantId, locationId, origin, destination }, false);
if(forceErrorWhenNotMatch)
var shouldBe = expectedResult ? "match" : "not match";
"because the input parameters [TenantId={0}, LocationId={1}, Origin={2}, Destination={3}] should {4} with the rule [{5}]",
tenantId, locationId, origin, destination, shouldBe, rule);
ResultDescription = matchResult == expectedResult ? "MATCH" : "NOT MATCH"
FiddleHelper.WriteTable($"{name} [{rule}]", r);
string DestinationCountry,
string ResultDescription = default);
public static class SettingsExtensions
private const string AllowsAnyWildcard = "*";
private static readonly char[] ConfigSeparators = {';'};
private static readonly char[] KeywordSeparators = {'-'};
private static readonly char[] ValueSeparators = {','};
public static bool MatchSettingsRules(this string settingsRules, List<string> matches, bool exactlyMatch = true)
static bool Matches(string keyword, string value)
var values = keyword.Split(ValueSeparators, StringSplitOptions.RemoveEmptyEntries);
var result = !string.IsNullOrEmpty(keyword)
&& !string.IsNullOrEmpty(value)
&& (values.Contains(value.Trim()) || keyword.Trim().Equals(AllowsAnyWildcard));
static bool ExactlyMatch(string k, string v)
=> k.Trim() == v.Trim() || k.Trim() == AllowsAnyWildcard;
if (string.IsNullOrEmpty(settingsRules))
var configurations = settingsRules.Split(ConfigSeparators, StringSplitOptions.RemoveEmptyEntries);
foreach (var config in configurations)
var keywords = config.Split(KeywordSeparators, StringSplitOptions.RemoveEmptyEntries).ToArray();
if (keywords.Length < matches.Count && configurations.Length == 1)
var keywordsMatched = new bool[keywords.Length];
for (var i = 0; i < keywords.Length; i++)
keywordsMatched[i] = exactlyMatch
? ExactlyMatch(keywords[i], matches[i])
: Matches(keywords[i], matches[i]);
if (keywordsMatched.All(r => r))