diff --git a/samples/Rules.Framework.InMemory.Sample/Engine/IContentTypes.cs b/samples/Rules.Framework.InMemory.Sample/Engine/IRuleSpecificationsProvider.cs similarity index 71% rename from samples/Rules.Framework.InMemory.Sample/Engine/IContentTypes.cs rename to samples/Rules.Framework.InMemory.Sample/Engine/IRuleSpecificationsProvider.cs index 4983e7ea..1306bacc 100644 --- a/samples/Rules.Framework.InMemory.Sample/Engine/IContentTypes.cs +++ b/samples/Rules.Framework.InMemory.Sample/Engine/IRuleSpecificationsProvider.cs @@ -3,9 +3,9 @@ namespace Rules.Framework.InMemory.Sample.Engine using System.Collections.Generic; using global::Rules.Framework.InMemory.Sample.Enums; - internal interface IContentTypes + internal interface IRuleSpecificationsProvider { - ContentTypes ContentType { get; } + RulesetNames[] Rulesets { get; } IEnumerable GetRulesSpecifications(); } diff --git a/samples/Rules.Framework.InMemory.Sample/Engine/RuleSpecification.cs b/samples/Rules.Framework.InMemory.Sample/Engine/RuleSpecification.cs index 5bae5f93..c569d868 100644 --- a/samples/Rules.Framework.InMemory.Sample/Engine/RuleSpecification.cs +++ b/samples/Rules.Framework.InMemory.Sample/Engine/RuleSpecification.cs @@ -8,6 +8,6 @@ internal class RuleSpecification { public RuleAddPriorityOption RuleAddPriorityOption { get; set; } - public RuleBuilderResult RuleBuilderResult { get; set; } + public RuleBuilderResult RuleBuilderResult { get; set; } } } \ No newline at end of file diff --git a/samples/Rules.Framework.InMemory.Sample/Engine/RulesBuilder.cs b/samples/Rules.Framework.InMemory.Sample/Engine/RulesBuilder.cs index 82d8bca7..2a0e6725 100644 --- a/samples/Rules.Framework.InMemory.Sample/Engine/RulesBuilder.cs +++ b/samples/Rules.Framework.InMemory.Sample/Engine/RulesBuilder.cs @@ -6,17 +6,20 @@ namespace Rules.Framework.InMemory.Sample.Engine internal class RulesBuilder { - private readonly IEnumerable contentTypes; + private readonly IEnumerable ruleSpecificationsRegistrars; - public RulesBuilder(IEnumerable contentTypes) => this.contentTypes = contentTypes; + public RulesBuilder(IEnumerable ruleSpecificationsProviders) => this.ruleSpecificationsRegistrars = ruleSpecificationsProviders; public async Task BuildAsync(IRulesEngine rulesEngine) { - foreach (var contentType in contentTypes) + foreach (var ruleSpecificationsProvider in ruleSpecificationsRegistrars) { - await rulesEngine.CreateContentTypeAsync(contentType.ContentType.ToString()); + foreach (var ruleset in ruleSpecificationsProvider.Rulesets) + { + await rulesEngine.CreateRulesetAsync(ruleset.ToString()); + } - var rulesSpecifications = contentType.GetRulesSpecifications(); + var rulesSpecifications = ruleSpecificationsProvider.GetRulesSpecifications(); foreach (var ruleSpecification in rulesSpecifications) { diff --git a/samples/Rules.Framework.InMemory.Sample/Engine/RulesService.cs b/samples/Rules.Framework.InMemory.Sample/Engine/RulesService.cs index f55db187..ce9d58f2 100644 --- a/samples/Rules.Framework.InMemory.Sample/Engine/RulesService.cs +++ b/samples/Rules.Framework.InMemory.Sample/Engine/RulesService.cs @@ -11,18 +11,18 @@ internal class RulesService { private readonly RulesEngineProvider rulesEngineProvider; - public RulesService(IEnumerable contentTypes) + public RulesService(IEnumerable ruleSpecificationsProviders) { - this.rulesEngineProvider = new RulesEngineProvider(new RulesBuilder(contentTypes)); + this.rulesEngineProvider = new RulesEngineProvider(new RulesBuilder(ruleSpecificationsProviders)); } public async Task MatchOneAsync( - ContentTypes contentType, + RulesetNames ruleset, DateTime dateTime, - IDictionary conditions) + IDictionary conditions) { - var rulesConditions = (conditions is null) ? new Condition[] { } : - conditions.Select(x => new Condition(x.Key, x.Value)) + var rulesConditions = (conditions is null) ? new Condition[] { } : + conditions.Select(x => new Condition(x.Key, x.Value)) .ToArray(); var rulesEngine = await @@ -31,13 +31,13 @@ public async Task MatchOneAsync( .ConfigureAwait(false); var match = await rulesEngine - .MakeGeneric() - .MatchOneAsync(contentType, dateTime, rulesConditions) + .MakeGeneric() + .MatchOneAsync(ruleset, dateTime, rulesConditions) .ConfigureAwait(false); if (match is null) { - var message = $"Error trying to match one rule. No rule was found {contentType} {dateTime} {string.Join(", ", conditions)}."; + var message = $"Error trying to match one rule. No rule was found {ruleset} {dateTime} {string.Join(", ", conditions)}."; throw new RulesNotFoundException(message); } diff --git a/samples/Rules.Framework.InMemory.Sample/Enums/ConditionTypes.cs b/samples/Rules.Framework.InMemory.Sample/Enums/ConditionNames.cs similarity index 57% rename from samples/Rules.Framework.InMemory.Sample/Enums/ConditionTypes.cs rename to samples/Rules.Framework.InMemory.Sample/Enums/ConditionNames.cs index cd020a5c..13110543 100644 --- a/samples/Rules.Framework.InMemory.Sample/Enums/ConditionTypes.cs +++ b/samples/Rules.Framework.InMemory.Sample/Enums/ConditionNames.cs @@ -1,29 +1,29 @@ namespace Rules.Framework.InMemory.Sample.Enums { - internal enum ConditionTypes + internal enum ConditionNames { /// - /// no condition type defined + /// no condition defined /// None = 0, /// - /// condition type to filter by royal numbers + /// condition to filter by royal numbers /// RoyalNumber = 1, /// - /// condition type to filter if the number can be divided by 3 + /// condition to filter if the number can be divided by 3 /// CanNumberBeDividedBy3 = 2, /// - /// condition type to filter if the number is prime + /// condition to filter if the number is prime /// IsPrimeNumber = 3, /// - /// condition type to filter number sums + /// condition to filter number sums /// SumAll = 4 } diff --git a/samples/Rules.Framework.InMemory.Sample/Enums/ContentTypes.cs b/samples/Rules.Framework.InMemory.Sample/Enums/RulesetNames.cs similarity index 57% rename from samples/Rules.Framework.InMemory.Sample/Enums/ContentTypes.cs rename to samples/Rules.Framework.InMemory.Sample/Enums/RulesetNames.cs index 4b4ee73c..b34981ee 100644 --- a/samples/Rules.Framework.InMemory.Sample/Enums/ContentTypes.cs +++ b/samples/Rules.Framework.InMemory.Sample/Enums/RulesetNames.cs @@ -1,11 +1,11 @@ namespace Rules.Framework.InMemory.Sample.Enums { - internal enum ContentTypes + internal enum RulesetNames { None = 0, /// - /// this content verifies if number is cool or not + /// this ruleset contains rules that verify if a number is cool or not /// TestNumber = 1, } diff --git a/samples/Rules.Framework.InMemory.Sample/Program.cs b/samples/Rules.Framework.InMemory.Sample/Program.cs index 7dced43a..002caeb8 100644 --- a/samples/Rules.Framework.InMemory.Sample/Program.cs +++ b/samples/Rules.Framework.InMemory.Sample/Program.cs @@ -3,6 +3,7 @@ namespace Rules.Framework.InMemory.Sample using System; using System.Collections.Generic; using System.Globalization; + using System.Threading.Tasks; using global::Rules.Framework.InMemory.Sample.Engine; using global::Rules.Framework.InMemory.Sample.Enums; using global::Rules.Framework.InMemory.Sample.Helper; @@ -10,9 +11,9 @@ namespace Rules.Framework.InMemory.Sample internal class Program { - private static void Main(string[] args) + private static async Task Main(string[] args) { - var rulesService = new RulesService(new List() + var rulesService = new RulesService(new List() { new TestNumberRules() }); @@ -31,18 +32,15 @@ private static void Main(string[] args) break; } - var conditions = new Dictionary { - { ConditionTypes.IsPrimeNumber, value.IsPrime() }, - { ConditionTypes.CanNumberBeDividedBy3, value.CanNumberBeDividedBy3() }, - { ConditionTypes.SumAll, value.SumAll() }, - { ConditionTypes.RoyalNumber, value } + var conditions = new Dictionary { + { ConditionNames.IsPrimeNumber, value.IsPrime() }, + { ConditionNames.CanNumberBeDividedBy3, value.CanNumberBeDividedBy3() }, + { ConditionNames.SumAll, value.SumAll() }, + { ConditionNames.RoyalNumber, value } }; - var result = rulesService - .MatchOneAsync(ContentTypes.TestNumber, targetDate, conditions) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); + var result = await rulesService + .MatchOneAsync(RulesetNames.TestNumber, targetDate, conditions); Console.WriteLine($"The result is: {result}"); } diff --git a/samples/Rules.Framework.InMemory.Sample/Rules/TestNumberRules.cs b/samples/Rules.Framework.InMemory.Sample/Rules/TestNumberRules.cs index 5409f683..797b4377 100644 --- a/samples/Rules.Framework.InMemory.Sample/Rules/TestNumberRules.cs +++ b/samples/Rules.Framework.InMemory.Sample/Rules/TestNumberRules.cs @@ -6,7 +6,7 @@ namespace Rules.Framework.InMemory.Sample.Rules using global::Rules.Framework.InMemory.Sample.Engine; using global::Rules.Framework.InMemory.Sample.Enums; - internal class TestNumberRules : IContentTypes + internal class TestNumberRules : IRuleSpecificationsProvider { public readonly List rulesSpecifications; @@ -15,7 +15,7 @@ public TestNumberRules() this.rulesSpecifications = new List(); } - public ContentTypes ContentType => ContentTypes.TestNumber; + public RulesetNames[] Rulesets => new[] { RulesetNames.TestNumber, }; public IEnumerable GetRulesSpecifications() { @@ -27,7 +27,7 @@ public IEnumerable GetRulesSpecifications() } private void Add( - RuleBuilderResult rule, + RuleBuilderResult rule, RuleAddPriorityOption ruleAddPriorityOption) => rulesSpecifications.Add( new RuleSpecification { @@ -35,33 +35,33 @@ private void Add( RuleAddPriorityOption = ruleAddPriorityOption, }); - private RuleBuilderResult CreateDefaultRule() => Rule.New() - .WithName("Default rule for test number") - .WithContent(ContentTypes.TestNumber, ":| default nothing special about this number") - .WithDateBegin(new DateTime(2019, 01, 01)) + private RuleBuilderResult CreateDefaultRule() => Rule.Create("Default rule for test number") + .InRuleset(RulesetNames.TestNumber) + .SetContent(":| default nothing special about this number") + .Since(new DateTime(2019, 01, 01)) .Build(); - private RuleBuilderResult CreateRuleForCoolNumbers() => Rule.New() - .WithName("Rule for cool numbers") - .WithContent(ContentTypes.TestNumber, ":D this number is so COOL!") - .WithDateBegin(new DateTime(2019, 01, 01)) - .WithCondition(c => c - .Or(o => o - .Value(ConditionTypes.RoyalNumber, Operators.Equal, 7) - .And(a => a - .Value(ConditionTypes.IsPrimeNumber, Operators.Equal, 7) - .Value(ConditionTypes.SumAll, Operators.StartsWith, "5")))) + private RuleBuilderResult CreateRuleForCoolNumbers() => Rule.Create("Rule for cool numbers") + .InRuleset(RulesetNames.TestNumber) + .SetContent(":D this number is so COOL!") + .Since(new DateTime(2019, 01, 01)) + .ApplyWhen(c => c + .Or(o => o + .Value(ConditionNames.RoyalNumber, Operators.Equal, 7) + .And(a => a + .Value(ConditionNames.IsPrimeNumber, Operators.Equal, 7) + .Value(ConditionNames.SumAll, Operators.StartsWith, "5")))) .Build(); - private RuleBuilderResult CreateRuleForSosoNumbers() => Rule.New() - .WithName("Rule for so so numbers") - .WithContent(ContentTypes.TestNumber, ":) this number is so so") - .WithDateBegin(new DateTime(2019, 01, 01)) - .WithCondition(c => c + private RuleBuilderResult CreateRuleForSosoNumbers() => Rule.Create("Rule for so so numbers") + .InRuleset(RulesetNames.TestNumber) + .SetContent(":) this number is so so") + .Since(new DateTime(2019, 01, 01)) + .ApplyWhen(c => c .Or(o => o - .Value(ConditionTypes.CanNumberBeDividedBy3, Operators.Equal, true) - .Value(ConditionTypes.IsPrimeNumber, Operators.Equal, false) - .Value(ConditionTypes.SumAll, Operators.StartsWith, "9"))) + .Value(ConditionNames.CanNumberBeDividedBy3, Operators.Equal, true) + .Value(ConditionNames.IsPrimeNumber, Operators.Equal, false) + .Value(ConditionNames.SumAll, Operators.StartsWith, "9"))) .Build(); } } \ No newline at end of file diff --git a/samples/Rules.Framework.WebUI.Sample/Engine/IContentTypes.cs b/samples/Rules.Framework.WebUI.Sample/Engine/IRuleSpecificationsProvider.cs similarity index 70% rename from samples/Rules.Framework.WebUI.Sample/Engine/IContentTypes.cs rename to samples/Rules.Framework.WebUI.Sample/Engine/IRuleSpecificationsProvider.cs index 2d4f988f..bddfce3d 100644 --- a/samples/Rules.Framework.WebUI.Sample/Engine/IContentTypes.cs +++ b/samples/Rules.Framework.WebUI.Sample/Engine/IRuleSpecificationsProvider.cs @@ -3,9 +3,9 @@ namespace Rules.Framework.WebUI.Sample.Engine using System.Collections.Generic; using global::Rules.Framework.WebUI.Sample.Enums; - internal interface IContentTypes + internal interface IRuleSpecificationsProvider { - ContentTypes[] ContentTypes { get; } + RulesetNames[] Rulesets { get; } IEnumerable GetRulesSpecifications(); } diff --git a/samples/Rules.Framework.WebUI.Sample/Engine/RuleSpecification.cs b/samples/Rules.Framework.WebUI.Sample/Engine/RuleSpecification.cs index 84749d4b..b39d330d 100644 --- a/samples/Rules.Framework.WebUI.Sample/Engine/RuleSpecification.cs +++ b/samples/Rules.Framework.WebUI.Sample/Engine/RuleSpecification.cs @@ -4,10 +4,10 @@ namespace Rules.Framework.WebUI.Sample.Engine using global::Rules.Framework.Builder.Generic; using global::Rules.Framework.WebUI.Sample.Enums; - internal sealed class RuleSpecification : RuleSpecificationBase + internal sealed class RuleSpecification : RuleSpecificationBase { public RuleSpecification( - RuleBuilderResult ruleBuilderResult, + RuleBuilderResult ruleBuilderResult, RuleAddPriorityOption ruleAddPriorityOption) : base(ruleBuilderResult, ruleAddPriorityOption) { diff --git a/samples/Rules.Framework.WebUI.Sample/Engine/RulesBuilder.cs b/samples/Rules.Framework.WebUI.Sample/Engine/RulesBuilder.cs index d0587bdd..daba8249 100644 --- a/samples/Rules.Framework.WebUI.Sample/Engine/RulesBuilder.cs +++ b/samples/Rules.Framework.WebUI.Sample/Engine/RulesBuilder.cs @@ -6,20 +6,20 @@ namespace Rules.Framework.WebUI.Sample.Engine internal class RulesBuilder { - private readonly IEnumerable contentTypes; + private readonly IEnumerable ruleSpecificationsProviders; - public RulesBuilder(IEnumerable contentTypes) => this.contentTypes = contentTypes; + public RulesBuilder(IEnumerable ruleSpecificationsProviders) => this.ruleSpecificationsProviders = ruleSpecificationsProviders; public async Task BuildAsync(IRulesEngine rulesEngine) { - foreach (var contentType in contentTypes) + foreach (var ruleSpecificationsProvider in ruleSpecificationsProviders) { - foreach (var contentTypeValue in contentType.ContentTypes) + foreach (var ruleset in ruleSpecificationsProvider.Rulesets) { - await rulesEngine.CreateContentTypeAsync(contentTypeValue.ToString()); + await rulesEngine.CreateRulesetAsync(ruleset.ToString()); } - var rulesSpecifications = contentType.GetRulesSpecifications(); + var rulesSpecifications = ruleSpecificationsProvider.GetRulesSpecifications(); foreach (var ruleSpecification in rulesSpecifications) { diff --git a/samples/Rules.Framework.WebUI.Sample/Enums/ConditionTypes.cs b/samples/Rules.Framework.WebUI.Sample/Enums/ConditionNames.cs similarity index 57% rename from samples/Rules.Framework.WebUI.Sample/Enums/ConditionTypes.cs rename to samples/Rules.Framework.WebUI.Sample/Enums/ConditionNames.cs index 46b77fd0..0809506b 100644 --- a/samples/Rules.Framework.WebUI.Sample/Enums/ConditionTypes.cs +++ b/samples/Rules.Framework.WebUI.Sample/Enums/ConditionNames.cs @@ -1,29 +1,29 @@ namespace Rules.Framework.WebUI.Sample.Enums { - public enum ConditionTypes + public enum ConditionNames { /// - /// no condition type defined + /// no condition defined /// None = 0, /// - /// condition type to filter by royal numbers + /// condition to filter by royal numbers /// RoyalNumber = 1, /// - /// condition type to filter if the number can be divided by 3 + /// condition to filter if the number can be divided by 3 /// CanNumberBeDividedBy3 = 2, /// - /// condition type to filter if the number is prime + /// condition to filter if the number is prime /// IsPrimeNumber = 3, /// - /// condition type to filter number sums + /// condition to filter number sums /// SumAll = 4 } diff --git a/samples/Rules.Framework.WebUI.Sample/Enums/ContentTypes.cs b/samples/Rules.Framework.WebUI.Sample/Enums/RulesetNames.cs similarity index 89% rename from samples/Rules.Framework.WebUI.Sample/Enums/ContentTypes.cs rename to samples/Rules.Framework.WebUI.Sample/Enums/RulesetNames.cs index 78d10b65..f9df938b 100644 --- a/samples/Rules.Framework.WebUI.Sample/Enums/ContentTypes.cs +++ b/samples/Rules.Framework.WebUI.Sample/Enums/RulesetNames.cs @@ -1,6 +1,6 @@ namespace Rules.Framework.WebUI.Sample.Enums { - public enum ContentTypes + public enum RulesetNames { TestNumber = 0, @@ -18,4 +18,4 @@ public enum ContentTypes TestBlob = 7 } -} +} \ No newline at end of file diff --git a/samples/Rules.Framework.WebUI.Sample/Program.cs b/samples/Rules.Framework.WebUI.Sample/Program.cs index 7ccd9f3d..36e947dd 100644 --- a/samples/Rules.Framework.WebUI.Sample/Program.cs +++ b/samples/Rules.Framework.WebUI.Sample/Program.cs @@ -50,14 +50,13 @@ private static void AddRulesFrameworkUI(IApplicationBuilder app, bool useReadmeE return; } - var rulesProvider = new RulesEngineProvider(new RulesBuilder(new List() + var rulesProvider = new RulesEngineProvider(new RulesBuilder(new List() { new RulesRandomFactory() })); var rulesEngine = rulesProvider .GetRulesEngineAsync() - .ConfigureAwait(false) .GetAwaiter() .GetResult(); diff --git a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionType.cs b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionNames.cs similarity index 75% rename from samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionType.cs rename to samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionNames.cs index 34e83242..9adf2580 100644 --- a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionType.cs +++ b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicConditionNames.cs @@ -1,6 +1,6 @@ namespace Rules.Framework.WebUI.Sample.ReadmeExample { - public enum BasicConditionType + public enum BasicConditionNames { ClientType = 1, Country = 2 diff --git a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesEngineExample.cs b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesEngineExample.cs index 47f0f912..38a8ae4f 100644 --- a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesEngineExample.cs +++ b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesEngineExample.cs @@ -2,6 +2,7 @@ namespace Rules.Framework.WebUI.Sample.ReadmeExample { using System; using global::Rules.Framework.WebUI.Sample.Engine; + using global::Rules.Framework.WebUI.Sample.Enums; internal class BasicRulesEngineExample { @@ -13,6 +14,8 @@ public BasicRulesEngineExample() .Configure(c => c.PriorityCriteria = PriorityCriterias.TopmostRuleWins) .Build(); + this.CreateRulesets(); + var rules = this.CreateRules(); this.AddRules(rules); @@ -20,47 +23,58 @@ public BasicRulesEngineExample() public IRulesEngine RulesEngine { get; } - protected void AddRules(IEnumerable> ruleSpecifications) + protected void AddRules(IEnumerable> ruleSpecifications) { foreach (var ruleSpecification in ruleSpecifications) { this.RulesEngine.AddRuleAsync(ruleSpecification.RuleBuilderResult.Rule, ruleSpecification.RuleAddPriorityOption) - .ConfigureAwait(false) .GetAwaiter() .GetResult(); } } - private IEnumerable> CreateRules() + protected void CreateRulesets() + { + foreach (var rulesetName in Enum.GetValues()) + { + this.RulesEngine.CreateRulesetAsync(rulesetName.ToString()) + .GetAwaiter() + .GetResult(); + } + } + + private IEnumerable> CreateRules() { - var ruleForPremiumFreeSampleJanuary = Rule.New() - .WithName("Rule for January sample for premium clients.") - .WithContent(BasicContentType.FreeSample, "SmallPerfumeSample") - .WithCondition(BasicConditionType.ClientType, Operators.Equal, "Premium") - .WithDatesInterval(new DateTime(2023, 01, 01), new DateTime(2023, 02, 01)) + var ruleForPremiumFreeSampleJanuary = Rule.Create("Rule for January sample for premium clients.") + .InRuleset(BasicRulesetNames.FreeSample) + .SetContent("SmallPerfumeSample") + .Since(new DateTime(2023, 01, 01)) + .Until(new DateTime(2023, 02, 01)) + .ApplyWhen(BasicConditionNames.ClientType, Operators.Equal, "Premium") .Build(); - var ruleForPremiumFreeSampleApril = Rule.New() - .WithName("Rule for April sample for premium clients.") - .WithContent(BasicContentType.FreeSample, "ShampooSample") - .WithCondition(BasicConditionType.ClientType, Operators.Equal, "Premium") - .WithDatesInterval(new DateTime(2023, 04, 01), new DateTime(2023, 05, 01)) + var ruleForPremiumFreeSampleApril = Rule.Create("Rule for April sample for premium clients.") + .InRuleset(BasicRulesetNames.FreeSample) + .SetContent("ShampooSample") + .Since(new DateTime(2023, 04, 01)) + .Until(new DateTime(2023, 05, 01)) + .ApplyWhen(BasicConditionNames.ClientType, Operators.Equal, "Premium") .Build(); - var ruleForPremiumFreeSampleSeptember = Rule.New() - .WithName("Rule for September sample for premium clients.") - .WithContent(BasicContentType.FreeSample, "ConditionerSample") - .WithCondition(BasicConditionType.ClientType, Operators.Equal, "Premium") - .WithDatesInterval(new DateTime(2023, 09, 01), new DateTime(2023, 10, 01)) + var ruleForPremiumFreeSampleSeptember = Rule.Create("Rule for September sample for premium clients.") + .InRuleset(BasicRulesetNames.FreeSample) + .SetContent("ConditionerSample") + .Since(new DateTime(2023, 09, 01)).Until(new DateTime(2023, 10, 01)) + .ApplyWhen(BasicConditionNames.ClientType, Operators.Equal, "Premium") .Build(); - return new List>() + return new List>() { - new RuleSpecificationBase( + new RuleSpecificationBase( ruleForPremiumFreeSampleJanuary, RuleAddPriorityOption.ByPriorityNumber(1)), - new RuleSpecificationBase( + new RuleSpecificationBase( ruleForPremiumFreeSampleApril, RuleAddPriorityOption.ByPriorityNumber(2)), - new RuleSpecificationBase( + new RuleSpecificationBase( ruleForPremiumFreeSampleSeptember, RuleAddPriorityOption.ByPriorityNumber(3)) }; } diff --git a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicContentType.cs b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesetNames.cs similarity index 77% rename from samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicContentType.cs rename to samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesetNames.cs index 891e6bec..495c47d7 100644 --- a/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicContentType.cs +++ b/samples/Rules.Framework.WebUI.Sample/ReadmeExample/BasicRulesetNames.cs @@ -1,6 +1,6 @@ namespace Rules.Framework.WebUI.Sample.ReadmeExample { - public enum BasicContentType + public enum BasicRulesetNames { FreeSample = 1, ShippingCost = 2 diff --git a/samples/Rules.Framework.WebUI.Sample/Rules/RulesRandomFactory.cs b/samples/Rules.Framework.WebUI.Sample/Rules/RulesRandomFactory.cs index de6c24c0..7e41098b 100644 --- a/samples/Rules.Framework.WebUI.Sample/Rules/RulesRandomFactory.cs +++ b/samples/Rules.Framework.WebUI.Sample/Rules/RulesRandomFactory.cs @@ -6,7 +6,7 @@ namespace Rules.Framework.WebUI.Sample.Rules using global::Rules.Framework.WebUI.Sample.Engine; using global::Rules.Framework.WebUI.Sample.Enums; - internal class RulesRandomFactory : IContentTypes + internal class RulesRandomFactory : IRuleSpecificationsProvider { private readonly int finalNumber = 50; private readonly int intialNumber = 10; @@ -17,16 +17,16 @@ public RulesRandomFactory() this.random = new Random(); } - public ContentTypes[] ContentTypes => new[] + public RulesetNames[] Rulesets => new[] { - Enums.ContentTypes.TestDateTime, - Enums.ContentTypes.TestDecimal, - Enums.ContentTypes.TestLong, - Enums.ContentTypes.TestBoolean, - Enums.ContentTypes.TestShort, - Enums.ContentTypes.TestNumber, - Enums.ContentTypes.TestString, - Enums.ContentTypes.TestBlob, + RulesetNames.TestDateTime, + RulesetNames.TestDecimal, + RulesetNames.TestLong, + RulesetNames.TestBoolean, + RulesetNames.TestShort, + RulesetNames.TestNumber, + RulesetNames.TestString, + RulesetNames.TestBlob, }; public IEnumerable GetRulesSpecifications() @@ -34,20 +34,20 @@ public IEnumerable GetRulesSpecifications() var currentYear = DateTime.UtcNow.Year; var rulesSpecifications = new List(); - foreach (var contentType in Enum.GetValues(typeof(ContentTypes))) + foreach (var ruleset in Enum.GetValues(typeof(RulesetNames)).Cast()) { for (var i = 1; i < random.Next(intialNumber, finalNumber); i++) { var dateBegin = CreateRandomDateBegin(currentYear); - Add(CreateMultipleRule((ContentTypes)contentType, i, dateBegin, CreateRandomDateEnd(dateBegin)), + Add(CreateMultipleRule(ruleset, i, dateBegin, CreateRandomDateEnd(dateBegin)), RuleAddPriorityOption.ByPriorityNumber(i), rulesSpecifications); } var deactiveDateBegin = CreateRandomDateBegin(currentYear); - Add(CreateMultipleRule((ContentTypes)contentType, finalNumber, deactiveDateBegin, CreateRandomDateEnd(deactiveDateBegin), isActive: false), + Add(CreateMultipleRule(ruleset, finalNumber, deactiveDateBegin, CreateRandomDateEnd(deactiveDateBegin), isActive: false), RuleAddPriorityOption.ByPriorityNumber(finalNumber), rulesSpecifications); } @@ -55,37 +55,38 @@ public IEnumerable GetRulesSpecifications() return rulesSpecifications; } - private static RuleBuilderResult CreateMultipleRule( - ContentTypes contentTypes, + private static RuleBuilderResult CreateMultipleRule( + RulesetNames ruleset, int value, DateTime dateBegin, DateTime? dateEnd, - bool isActive = true) => Rule.New() - .WithName($"Multi rule for test {contentTypes} {value}") - .WithContent(contentTypes, new { Value = value }) - .WithDatesInterval(dateBegin, dateEnd) + bool isActive = true) => Rule.Create($"Multi rule for test {ruleset} {value}") + .InRuleset(ruleset) + .SetContent(new { Value = value }) + .Since(dateBegin) + .Until(dateEnd) .WithActive(isActive) - .WithCondition(rootCond => rootCond + .ApplyWhen(rootCond => rootCond .Or(o => o - .Value(ConditionTypes.RoyalNumber, Operators.Equal, 7) - .Value(ConditionTypes.SumAll, Operators.In, new int[] { 9, 8, 6 }) + .Value(ConditionNames.RoyalNumber, Operators.Equal, 7) + .Value(ConditionNames.SumAll, Operators.In, new int[] { 9, 8, 6 }) .And(a => a - .Value(ConditionTypes.IsPrimeNumber, Operators.Equal, false) - .Value(ConditionTypes.SumAll, Operators.StartsWith, "15") + .Value(ConditionNames.IsPrimeNumber, Operators.Equal, false) + .Value(ConditionNames.SumAll, Operators.StartsWith, "15") ) .And(a => a - .Value(ConditionTypes.CanNumberBeDividedBy3, Operators.Equal, false) - .Value(ConditionTypes.SumAll, Operators.NotEqual, string.Empty) + .Value(ConditionNames.CanNumberBeDividedBy3, Operators.Equal, false) + .Value(ConditionNames.SumAll, Operators.NotEqual, string.Empty) ) .And(a => a - .Value(ConditionTypes.IsPrimeNumber, Operators.Equal, true) - .Value(ConditionTypes.SumAll, Operators.StartsWith, "5") - .Value(ConditionTypes.CanNumberBeDividedBy3, Operators.Equal, false) + .Value(ConditionNames.IsPrimeNumber, Operators.Equal, true) + .Value(ConditionNames.SumAll, Operators.StartsWith, "5") + .Value(ConditionNames.CanNumberBeDividedBy3, Operators.Equal, false) ))) .Build(); private void Add( - RuleBuilderResult rule, + RuleBuilderResult rule, RuleAddPriorityOption ruleAddPriorityOption, List rulesSpecifications) => rulesSpecifications.Add(new RuleSpecification(rule, ruleAddPriorityOption)); diff --git a/src/Rules.Framework.Providers.MongoDb/DataModel/RuleDataModel.cs b/src/Rules.Framework.Providers.MongoDb/DataModel/RuleDataModel.cs index 25f4078b..6042d3c5 100644 --- a/src/Rules.Framework.Providers.MongoDb/DataModel/RuleDataModel.cs +++ b/src/Rules.Framework.Providers.MongoDb/DataModel/RuleDataModel.cs @@ -11,9 +11,6 @@ internal sealed class RuleDataModel [BsonElement(Order = 7)] public dynamic Content { get; set; } - [BsonElement(Order = 2)] - public string ContentType { get; set; } - [BsonElement(Order = 3)] public DateTime DateBegin { get; set; } @@ -28,5 +25,8 @@ internal sealed class RuleDataModel [BsonElement(Order = 6)] public ConditionNodeDataModel RootCondition { get; set; } + + [BsonElement(Order = 2)] + public string Ruleset { get; set; } } } \ No newline at end of file diff --git a/src/Rules.Framework.Providers.MongoDb/DataModel/ContentTypeDataModel.cs b/src/Rules.Framework.Providers.MongoDb/DataModel/RulesetDataModel.cs similarity index 90% rename from src/Rules.Framework.Providers.MongoDb/DataModel/ContentTypeDataModel.cs rename to src/Rules.Framework.Providers.MongoDb/DataModel/RulesetDataModel.cs index b185b3c6..3e300b81 100644 --- a/src/Rules.Framework.Providers.MongoDb/DataModel/ContentTypeDataModel.cs +++ b/src/Rules.Framework.Providers.MongoDb/DataModel/RulesetDataModel.cs @@ -3,7 +3,7 @@ namespace Rules.Framework.Providers.MongoDb.DataModel using System; using MongoDB.Bson.Serialization.Attributes; - internal class ContentTypeDataModel + internal class RulesetDataModel { [BsonElement("creation", Order = 3)] public DateTime Creation { get; set; } diff --git a/src/Rules.Framework.Providers.MongoDb/DataModel/ValueConditionNodeDataModel.cs b/src/Rules.Framework.Providers.MongoDb/DataModel/ValueConditionNodeDataModel.cs index 05853a12..84b4c683 100644 --- a/src/Rules.Framework.Providers.MongoDb/DataModel/ValueConditionNodeDataModel.cs +++ b/src/Rules.Framework.Providers.MongoDb/DataModel/ValueConditionNodeDataModel.cs @@ -7,17 +7,17 @@ namespace Rules.Framework.Providers.MongoDb.DataModel internal sealed class ValueConditionNodeDataModel : ConditionNodeDataModel { [BsonElement(Order = 1)] - public string ConditionType { get; set; } + public string Condition { get; set; } [BsonElement(Order = 2)] [BsonRepresentation(MongoDB.Bson.BsonType.String)] public DataTypes DataType { get; set; } - - [BsonElement(Order = 3)] - [BsonRepresentation(MongoDB.Bson.BsonType.String)] - public Operators Operator { get; set; } [BsonElement(Order = 4)] public object Operand { get; set; } + + [BsonElement(Order = 3)] + [BsonRepresentation(MongoDB.Bson.BsonType.String)] + public Operators Operator { get; set; } } } \ No newline at end of file diff --git a/src/Rules.Framework.Providers.MongoDb/MongoDbProviderRulesDataSource.cs b/src/Rules.Framework.Providers.MongoDb/MongoDbProviderRulesDataSource.cs index f027618f..a69eb0c3 100644 --- a/src/Rules.Framework.Providers.MongoDb/MongoDbProviderRulesDataSource.cs +++ b/src/Rules.Framework.Providers.MongoDb/MongoDbProviderRulesDataSource.cs @@ -46,55 +46,37 @@ public async Task AddRuleAsync(Rule rule) } /// - /// Creates a new content type on the data source. + /// Creates a new ruleset on the data source. /// /// Type of the content. - public async Task CreateContentTypeAsync(string contentType) + public async Task CreateRulesetAsync(string contentType) { - var contentTypesCollection = this.mongoDatabase.GetCollection(this.mongoDbProviderSettings.ContentTypesCollectionName); + var rulesetsCollection = this.mongoDatabase.GetCollection(this.mongoDbProviderSettings.RulesetsCollectionName); - var contentTypeDataModel = new ContentTypeDataModel + var rulesetDataModel = new RulesetDataModel { Creation = DateTime.UtcNow, Id = Guid.NewGuid(), Name = contentType, }; - await contentTypesCollection.InsertOneAsync(contentTypeDataModel).ConfigureAwait(false); + await rulesetsCollection.InsertOneAsync(rulesetDataModel).ConfigureAwait(false); } /// - /// Gets the content types from the data source. - /// - /// - public async Task> GetContentTypesAsync() - { - var contentTypesCollection = this.mongoDatabase.GetCollection(this.mongoDbProviderSettings.ContentTypesCollectionName); - - var findAllFilterDefinition = FilterDefinition.Empty; - var findOptions = new FindOptions - { - Projection = Builders.Projection.Expression(x => x.Name), - }; - - var resultsCursor = await contentTypesCollection.FindAsync(findAllFilterDefinition, findOptions).ConfigureAwait(false); - return await resultsCursor.ToListAsync().ConfigureAwait(false); - } - - /// - /// Gets the rules categorized with specified between - /// and . + /// Gets the rules categorized with specified between and . /// - /// the content type categorization. + /// the ruleset name. /// the filtering begin date. /// the filtering end date. /// - public async Task> GetRulesAsync(string contentType, DateTime dateBegin, DateTime dateEnd) + public async Task> GetRulesAsync(string ruleset, DateTime dateBegin, DateTime dateEnd) { - var getRulesByContentTypeAndDatesInterval = MongoDbProviderRulesDataSource - .BuildFilterByContentTypeAndDatesInterval(contentType, dateBegin, dateEnd); + var getRulesByRulesetAndDatesInterval = MongoDbProviderRulesDataSource + .BuildFilterByContentTypeAndDatesInterval(ruleset, dateBegin, dateEnd); - return await this.GetRulesAsync(getRulesByContentTypeAndDatesInterval).ConfigureAwait(false); + return await this.GetRulesAsync(getRulesByRulesetAndDatesInterval).ConfigureAwait(false); } /// @@ -115,6 +97,29 @@ public Task> GetRulesByAsync(RulesFilterArgs rulesFilterArgs) return this.GetRulesAsync(filterDefinition); } + /// + /// Gets the content types from the data source. + /// + /// + public async Task> GetRulesetsAsync() + { + var rulesetsCollection = this.mongoDatabase.GetCollection(this.mongoDbProviderSettings.RulesetsCollectionName); + + var findAllFilterDefinition = FilterDefinition.Empty; + + var resultsCursor = await rulesetsCollection.FindAsync(findAllFilterDefinition).ConfigureAwait(false); + var rulesets = new List(); + while (await resultsCursor.MoveNextAsync().ConfigureAwait(false)) + { + foreach (var rulesetDataModel in resultsCursor.Current) + { + rulesets.Add(new Ruleset(rulesetDataModel.Name, rulesetDataModel.Creation)); + } + } + + return rulesets; + } + /// /// Updates the existent rule on data source. /// @@ -130,7 +135,7 @@ public async Task UpdateRuleAsync(Rule rule) var updateDefinitions = new UpdateDefinition[] { Builders.Update.Set(contentField, (object)ruleDataModel.Content), - Builders.Update.Set(r => r.ContentType, ruleDataModel.ContentType), + Builders.Update.Set(r => r.Ruleset, ruleDataModel.Ruleset), Builders.Update.Set(r => r.DateBegin, ruleDataModel.DateBegin), Builders.Update.Set(r => r.DateEnd, ruleDataModel.DateEnd), Builders.Update.Set(r => r.Name, ruleDataModel.Name), @@ -144,9 +149,9 @@ public async Task UpdateRuleAsync(Rule rule) await rulesCollection.UpdateOneAsync(filterDefinition, updateDefinition).ConfigureAwait(false); } - private static FilterDefinition BuildFilterByContentTypeAndDatesInterval(string contentType, DateTime dateBegin, DateTime dateEnd) + private static FilterDefinition BuildFilterByContentTypeAndDatesInterval(string ruleset, DateTime dateBegin, DateTime dateEnd) { - var contentTypeFilter = Builders.Filter.Eq(x => x.ContentType, contentType); + var rulesetFilter = Builders.Filter.Eq(x => x.Ruleset, ruleset); var datesFilter = Builders.Filter.And( Builders.Filter.Lte(rule => rule.DateBegin, dateEnd), @@ -155,16 +160,16 @@ private static FilterDefinition BuildFilterByContentTypeAndDatesI Builders.Filter.Eq(rule => rule.DateEnd, null)) ); - return Builders.Filter.And(contentTypeFilter, datesFilter); + return Builders.Filter.And(rulesetFilter, datesFilter); } private static FilterDefinition BuildFilterFromRulesFilterArgs(RulesFilterArgs rulesFilterArgs) { var filtersToApply = new List>(3); - if (!object.Equals(rulesFilterArgs.ContentType, default(string))) + if (!object.Equals(rulesFilterArgs.Ruleset, default(string))) { - filtersToApply.Add(Builders.Filter.Eq(x => x.ContentType, rulesFilterArgs.ContentType)); + filtersToApply.Add(Builders.Filter.Eq(x => x.Ruleset, rulesFilterArgs.Ruleset)); } if (!string.IsNullOrWhiteSpace(rulesFilterArgs.Name)) diff --git a/src/Rules.Framework.Providers.MongoDb/MongoDbProviderSettings.cs b/src/Rules.Framework.Providers.MongoDb/MongoDbProviderSettings.cs index 4d4075e8..1a0be271 100644 --- a/src/Rules.Framework.Providers.MongoDb/MongoDbProviderSettings.cs +++ b/src/Rules.Framework.Providers.MongoDb/MongoDbProviderSettings.cs @@ -5,22 +5,16 @@ namespace Rules.Framework.Providers.MongoDb /// public class MongoDbProviderSettings { - private const string DefaultContentTypesCollectionName = "content_types"; + private const string DefaultRulesetsCollectionName = "rulesets"; /// /// Initializes a new instance of the class. /// public MongoDbProviderSettings() { - this.ContentTypesCollectionName = DefaultContentTypesCollectionName; + this.RulesetsCollectionName = DefaultRulesetsCollectionName; } - /// - /// Gets or sets the name of the content types collection. - /// - /// The name of the content types collection. - public string ContentTypesCollectionName { get; set; } - /// /// Gets or sets the name of the database. /// @@ -32,5 +26,11 @@ public MongoDbProviderSettings() /// /// The name of the rules collection. public string RulesCollectionName { get; set; } + + /// + /// Gets or sets the name of the rulesets collection. + /// + /// The name of the content types collection. + public string RulesetsCollectionName { get; set; } } } \ No newline at end of file diff --git a/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceInitializer.cs b/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceInitializer.cs index 5850611f..1fb83f7a 100644 --- a/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceInitializer.cs +++ b/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceInitializer.cs @@ -34,27 +34,49 @@ public static async Task InitializeAsync(IMongoClient mongoClient, MongoDbProvid WriteConcern = WriteConcern.Acknowledged, }); - await CreateRulesCollectionIfNotExists(mongoDatabase, mongoDbProviderSettings).ConfigureAwait(false); - - var rulesCollection = mongoDatabase.GetCollection(mongoDbProviderSettings.RulesCollectionName); - - await CreateIndexesIfNotExists(rulesCollection, mongoDbProviderSettings).ConfigureAwait(false); + await CreateCollectionsIfNotExists(mongoDatabase, mongoDbProviderSettings).ConfigureAwait(false); + await CreateIndexesIfNotExists(mongoDatabase, mongoDbProviderSettings).ConfigureAwait(false); // Mark as initialized as this initialization code is never run anymore throughout the // app lifecycle. isInitialized = true; } - private static async Task CreateIndexesIfNotExists(IMongoCollection rulesCollection, MongoDbProviderSettings mongoDbProviderSettings) + private static async Task CreateCollectionsIfNotExists(IMongoDatabase mongoDatabase, MongoDbProviderSettings mongoDbProviderSettings) { - var getRulesIndex = $"ix_{mongoDbProviderSettings.RulesCollectionName.ToLower(CultureInfo.InvariantCulture)}_get_rules"; - var getRulesIndexKeysDefinition = Builders.IndexKeys - .Ascending("ContentType").Ascending("DateBegin").Ascending("DateEnd"); - await CreateIndexOnBackgroundAsync(rulesCollection, getRulesIndex, getRulesIndexKeysDefinition).ConfigureAwait(false); - var getRulesByIndex = $"ix_{mongoDbProviderSettings.RulesCollectionName.ToLower(CultureInfo.InvariantCulture)}_get_rules_by"; - var getRulesByIndexKeysDefinition = Builders.IndexKeys - .Ascending("ContentType").Ascending("Name").Ascending("Priority"); - await CreateIndexOnBackgroundAsync(rulesCollection, getRulesByIndex, getRulesByIndexKeysDefinition).ConfigureAwait(false); + var collectionsCursor = await mongoDatabase.ListCollectionNamesAsync().ConfigureAwait(false); + var collections = await collectionsCursor.ToListAsync().ConfigureAwait(false); + + if (!collections.Contains(mongoDbProviderSettings.RulesetsCollectionName)) + { + await mongoDatabase.CreateCollectionAsync(mongoDbProviderSettings.RulesetsCollectionName).ConfigureAwait(false); + } + + if (!collections.Contains(mongoDbProviderSettings.RulesCollectionName)) + { + await mongoDatabase.CreateCollectionAsync(mongoDbProviderSettings.RulesCollectionName).ConfigureAwait(false); + } + } + + private static async Task CreateIndexesIfNotExists(IMongoDatabase mongoDatabase, MongoDbProviderSettings mongoDbProviderSettings) + { + var rulesetsCollection = mongoDatabase.GetCollection(mongoDbProviderSettings.RulesetsCollectionName); + var rulesCollection = mongoDatabase.GetCollection(mongoDbProviderSettings.RulesCollectionName); + + var rulesetsByNameIndexName = $"ix_{mongoDbProviderSettings.RulesetsCollectionName.ToLower(CultureInfo.InvariantCulture)}_rulesets_by_name"; + var rulesetsByNameIndexKeys = Builders.IndexKeys + .Ascending(x => x.Name); + await CreateIndexOnBackgroundAsync(rulesetsCollection, rulesetsByNameIndexName, rulesetsByNameIndexKeys).ConfigureAwait(false); + + var rulesByRulesetAndDatesIndexName = $"ix_{mongoDbProviderSettings.RulesCollectionName.ToLower(CultureInfo.InvariantCulture)}_rules_by_ruleset_and_dates"; + var rulesByRulesetAndDatesIndexKeys = Builders.IndexKeys + .Ascending(x => x.Ruleset).Ascending(x => x.DateBegin).Ascending(x => x.DateEnd); + await CreateIndexOnBackgroundAsync(rulesCollection, rulesByRulesetAndDatesIndexName, rulesByRulesetAndDatesIndexKeys).ConfigureAwait(false); + + var rulesByRulesetNamePriorityIndexName = $"ix_{mongoDbProviderSettings.RulesCollectionName.ToLower(CultureInfo.InvariantCulture)}_rules_by_ruleset_name_priority"; + var rulesByRulesetNamePriorityIndexKeys = Builders.IndexKeys + .Ascending(x => x.Ruleset).Ascending(x => x.Name).Ascending(x => x.Priority); + await CreateIndexOnBackgroundAsync(rulesCollection, rulesByRulesetNamePriorityIndexName, rulesByRulesetNamePriorityIndexKeys).ConfigureAwait(false); } private static async Task CreateIndexOnBackgroundAsync(IMongoCollection mongoCollection, string indexName, IndexKeysDefinition indexKeysDefinition) @@ -67,15 +89,5 @@ private static async Task CreateIndexOnBackgroundAsync(IMongoCollection mo var createIndexModel = new CreateIndexModel(indexKeysDefinition, createIndexOptions); _ = await mongoCollection.Indexes.CreateOneAsync(createIndexModel).ConfigureAwait(false); } - - private static async Task CreateRulesCollectionIfNotExists(IMongoDatabase mongoDatabase, MongoDbProviderSettings mongoDbProviderSettings) - { - var collectionsCursor = await mongoDatabase.ListCollectionNamesAsync().ConfigureAwait(false); - var collections = await collectionsCursor.ToListAsync().ConfigureAwait(false); - if (!collections.Contains(mongoDbProviderSettings.RulesCollectionName)) - { - await mongoDatabase.CreateCollectionAsync(mongoDbProviderSettings.RulesCollectionName).ConfigureAwait(false); - } - } } } \ No newline at end of file diff --git a/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceSelectorExtensions.cs b/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceSelectorExtensions.cs index 4a2c0a2c..641b59f6 100644 --- a/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceSelectorExtensions.cs +++ b/src/Rules.Framework.Providers.MongoDb/MongoDbRulesDataSourceSelectorExtensions.cs @@ -14,8 +14,6 @@ public static class MongoDbRulesDataSourceSelectorExtensions /// /// Sets the rules engine data source from a Mongo DB database. /// - /// The type of the content type. - /// The type of the condition type. /// The rules data source selector. /// The mongo client. /// The mongo database provider settings. diff --git a/src/Rules.Framework.Providers.MongoDb/RuleFactory.cs b/src/Rules.Framework.Providers.MongoDb/RuleFactory.cs index d6e6f94b..6083aa5f 100644 --- a/src/Rules.Framework.Providers.MongoDb/RuleFactory.cs +++ b/src/Rules.Framework.Providers.MongoDb/RuleFactory.cs @@ -24,12 +24,13 @@ public Rule CreateRule(RuleDataModel ruleDataModel) throw new ArgumentNullException(nameof(ruleDataModel)); } - var ruleBuilderResult = Rule.New() - .WithName(ruleDataModel.Name) - .WithDatesInterval(ruleDataModel.DateBegin, ruleDataModel.DateEnd) + var ruleBuilderResult = Rule.Create(ruleDataModel.Name) + .InRuleset(ruleDataModel.Ruleset) + .SetContent((object)ruleDataModel.Content, this.contentSerializationProvider) + .Since(ruleDataModel.DateBegin) + .Until(ruleDataModel.DateEnd) .WithActive(ruleDataModel.Active ?? true) - .WithCondition(_ => ruleDataModel.RootCondition is { } ? ConvertConditionNode(ruleDataModel.RootCondition) : null) - .WithSerializedContent(ruleDataModel.ContentType, (object)ruleDataModel.Content, this.contentSerializationProvider) + .ApplyWhen(_ => ruleDataModel.RootCondition is { } ? ConvertConditionNode(ruleDataModel.RootCondition) : null) .Build(); if (!ruleBuilderResult.IsSuccess) @@ -57,18 +58,18 @@ public RuleDataModel CreateRule(Rule rule) } var content = rule.ContentContainer.GetContentAs(); - var serializedContent = this.contentSerializationProvider.GetContentSerializer(rule.ContentType).Serialize(content); + var serializedContent = this.contentSerializationProvider.GetContentSerializer(rule.Ruleset).Serialize(content); var ruleDataModel = new RuleDataModel { + Active = rule.Active, Content = serializedContent, - ContentType = rule.ContentType, DateBegin = rule.DateBegin, DateEnd = rule.DateEnd, Name = rule.Name, Priority = rule.Priority, - Active = rule.Active, RootCondition = rule.RootCondition is { } ? ConvertConditionNode(rule.RootCondition) : null, + Ruleset = rule.Ruleset, }; return ruleDataModel; @@ -107,7 +108,7 @@ private static ValueConditionNodeDataModel ConvertValueConditionNode(ValueCondit return new ValueConditionNodeDataModel { - ConditionType = Convert.ToString(valueConditionNode.ConditionType, CultureInfo.InvariantCulture), + Condition = Convert.ToString(valueConditionNode.Condition, CultureInfo.InvariantCulture), LogicalOperator = LogicalOperators.Eval, DataType = valueConditionNode.DataType, Operand = valueConditionNode.Operand, @@ -130,7 +131,7 @@ private static ValueConditionNode CreateValueConditionNode(ValueConditionNodeDat var valueConditionNode = new ValueConditionNode( conditionNodeDataModel.DataType, - conditionNodeDataModel.ConditionType, + conditionNodeDataModel.Condition, conditionNodeDataModel.Operator, operand); diff --git a/src/Rules.Framework.WebUI/Dto/RuleDto.cs b/src/Rules.Framework.WebUI/Dto/RuleDto.cs index 24ae31c6..a122b80b 100644 --- a/src/Rules.Framework.WebUI/Dto/RuleDto.cs +++ b/src/Rules.Framework.WebUI/Dto/RuleDto.cs @@ -3,12 +3,12 @@ namespace Rules.Framework.WebUI.Dto internal sealed class RuleDto { public ConditionNodeDto Conditions { get; internal set; } - public string ContentType { get; internal set; } public string DateBegin { get; internal set; } public string DateEnd { get; internal set; } public string Name { get; internal set; } public int? Priority { get; internal set; } + public string Ruleset { get; internal set; } public string Status { get; internal set; } public object Value { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Rules.Framework.WebUI/Dto/FilterDto.cs b/src/Rules.Framework.WebUI/Dto/RulesFilterDto.cs similarity index 87% rename from src/Rules.Framework.WebUI/Dto/FilterDto.cs rename to src/Rules.Framework.WebUI/Dto/RulesFilterDto.cs index f90eb976..98fbed29 100644 --- a/src/Rules.Framework.WebUI/Dto/FilterDto.cs +++ b/src/Rules.Framework.WebUI/Dto/RulesFilterDto.cs @@ -5,10 +5,10 @@ namespace Rules.Framework.WebUI.Dto internal sealed class RulesFilterDto { public string Content { get; set; } - public string ContentType { get; set; } public DateTime? DateBegin { get; set; } public DateTime? DateEnd { get; set; } public string Name { get; set; } + public string Ruleset { get; set; } public RuleStatusDto? Status { get; set; } } -} +} \ No newline at end of file diff --git a/src/Rules.Framework.WebUI/Dto/ContentTypeDto.cs b/src/Rules.Framework.WebUI/Dto/RulesetDto.cs similarity index 86% rename from src/Rules.Framework.WebUI/Dto/ContentTypeDto.cs rename to src/Rules.Framework.WebUI/Dto/RulesetDto.cs index 6b4af554..d92ea633 100644 --- a/src/Rules.Framework.WebUI/Dto/ContentTypeDto.cs +++ b/src/Rules.Framework.WebUI/Dto/RulesetDto.cs @@ -1,6 +1,6 @@ namespace Rules.Framework.WebUI.Dto { - internal sealed class ContentTypeDto + internal sealed class RulesetDto { public int Index { get; internal set; } public int ActiveRulesCount { get; internal set; } diff --git a/src/Rules.Framework.WebUI/Dto/ValueConditionNodeDto.cs b/src/Rules.Framework.WebUI/Dto/ValueConditionNodeDto.cs index 7c9e3f8d..46d67539 100644 --- a/src/Rules.Framework.WebUI/Dto/ValueConditionNodeDto.cs +++ b/src/Rules.Framework.WebUI/Dto/ValueConditionNodeDto.cs @@ -2,7 +2,7 @@ namespace Rules.Framework.WebUI.Dto { internal sealed class ValueConditionNodeDto : ConditionNodeDto { - public string ConditionTypeName { get; internal set; } + public string Condition { get; internal set; } public string DataType { get; internal set; } @@ -10,4 +10,4 @@ internal sealed class ValueConditionNodeDto : ConditionNodeDto public string Operator { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Rules.Framework.WebUI/Extensions/RuleDtoExtensions.cs b/src/Rules.Framework.WebUI/Extensions/RuleDtoExtensions.cs index eeee5cc8..0bfabeb3 100644 --- a/src/Rules.Framework.WebUI/Extensions/RuleDtoExtensions.cs +++ b/src/Rules.Framework.WebUI/Extensions/RuleDtoExtensions.cs @@ -18,7 +18,7 @@ public static ConditionNodeDto ToConditionNodeDto(this IConditionNode rootCondit return new ValueConditionNodeDto { - ConditionTypeName = condition.ConditionType, + Condition = condition.Condition, DataType = condition.DataType.ToString(), Operand = condition.Operand, Operator = condition.Operator.ToString(), @@ -41,18 +41,18 @@ public static ConditionNodeDto ToConditionNodeDto(this IConditionNode rootCondit }; } - public static RuleDto ToRuleDto(this Rule rule, string ContentType, IRuleStatusDtoAnalyzer ruleStatusDtoAnalyzer) + public static RuleDto ToRuleDto(this Rule rule, IRuleStatusDtoAnalyzer ruleStatusDtoAnalyzer) { return new RuleDto { Conditions = rule.RootCondition?.ToConditionNodeDto(), - ContentType = ContentType, - Priority = rule.Priority, - Name = rule.Name, - Value = rule.ContentContainer.GetContentAs(), DateEnd = !rule.DateEnd.HasValue ? null : rule.DateEnd.Value.ToString(dateFormat), DateBegin = rule.DateBegin.ToString(dateFormat), + Name = rule.Name, + Priority = rule.Priority, + Ruleset = rule.Ruleset, Status = !rule.Active ? RuleStatusDto.Deactivated.ToString() : ruleStatusDtoAnalyzer.Analyze(rule.DateBegin, rule.DateEnd).ToString(), + Value = rule.ContentContainer.GetContentAs(), }; } } diff --git a/src/Rules.Framework.WebUI/Handlers/GetRulesHandler.cs b/src/Rules.Framework.WebUI/Handlers/GetRulesHandler.cs index 020e354e..4999cbc7 100644 --- a/src/Rules.Framework.WebUI/Handlers/GetRulesHandler.cs +++ b/src/Rules.Framework.WebUI/Handlers/GetRulesHandler.cs @@ -43,20 +43,20 @@ protected override async Task HandleRequestAsync(HttpRequest httpRequest, { var rules = new List(); - if (rulesFilter.ContentType.Equals("all")) + if (rulesFilter.Ruleset.Equals("all")) { - var contents = await this.rulesEngine.GetContentTypesAsync(); + var rulesets = await this.rulesEngine.GetRulesetsAsync(); - foreach (var identifier in contents) + foreach (var ruleset in rulesets) { - var rulesForContentType = await this.GetRulesForContentyType(identifier, rulesFilter).ConfigureAwait(false); - rules.AddRange(rulesForContentType); + var rulesForRuleset = await this.GetRulesForRuleset(ruleset.Name, rulesFilter).ConfigureAwait(false); + rules.AddRange(rulesForRuleset); } } else { - var rulesForContentType = await this.GetRulesForContentyType(rulesFilter.ContentType, rulesFilter).ConfigureAwait(false); - rules.AddRange(rulesForContentType); + var rulesForRuleset = await this.GetRulesForRuleset(rulesFilter.Ruleset, rulesFilter).ConfigureAwait(false); + rules.AddRange(rulesForRuleset); } await this.WriteResponseAsync(httpResponse, rules, (int)HttpStatusCode.OK).ConfigureAwait(false); @@ -117,7 +117,7 @@ private RulesFilterDto GetRulesFilterFromRequest(HttpRequest httpRequest) var rulesFilterAsString = JsonSerializer.Serialize(parseQueryString.Cast().ToDictionary(k => k, v => string.IsNullOrWhiteSpace(parseQueryString[v]) ? null : parseQueryString[v])); var rulesFilter = JsonSerializer.Deserialize(rulesFilterAsString, this.SerializerOptions); - rulesFilter.ContentType = string.IsNullOrWhiteSpace(rulesFilter.ContentType) ? "all" : rulesFilter.ContentType; + rulesFilter.Ruleset = string.IsNullOrWhiteSpace(rulesFilter.Ruleset) ? "all" : rulesFilter.Ruleset; rulesFilter.DateEnd ??= DateTime.MaxValue; @@ -126,11 +126,11 @@ private RulesFilterDto GetRulesFilterFromRequest(HttpRequest httpRequest) return rulesFilter; } - private async Task> GetRulesForContentyType(string identifier, RulesFilterDto rulesFilter) + private async Task> GetRulesForRuleset(string ruleset, RulesFilterDto rulesFilter) { var genericRules = await this.rulesEngine.SearchAsync( new SearchArgs( - identifier, + ruleset, rulesFilter.DateBegin.Value, rulesFilter.DateEnd.Value)) .ConfigureAwait(false); @@ -148,7 +148,7 @@ private async Task> GetRulesForContentyType(string identifi genericRules = genericRules.OrderBy(r => r.Priority); } - var genericRulesDto = this.ApplyFilters(rulesFilter, genericRules.Select(g => g.ToRuleDto(identifier, this.ruleStatusDtoAnalyzer))); + var genericRulesDto = this.ApplyFilters(rulesFilter, genericRules.Select(g => g.ToRuleDto(this.ruleStatusDtoAnalyzer))); return genericRulesDto; } diff --git a/src/Rules.Framework.WebUI/Handlers/GetContentTypeHandler.cs b/src/Rules.Framework.WebUI/Handlers/GetRulesetsHandler.cs similarity index 67% rename from src/Rules.Framework.WebUI/Handlers/GetContentTypeHandler.cs rename to src/Rules.Framework.WebUI/Handlers/GetRulesetsHandler.cs index 96303f4e..dbd1bd6a 100644 --- a/src/Rules.Framework.WebUI/Handlers/GetContentTypeHandler.cs +++ b/src/Rules.Framework.WebUI/Handlers/GetRulesetsHandler.cs @@ -8,14 +8,14 @@ namespace Rules.Framework.WebUI.Handlers using Microsoft.AspNetCore.Http; using Rules.Framework.WebUI.Dto; - internal sealed class GetContentTypeHandler : WebUIRequestHandlerBase + internal sealed class GetRulesetsHandler : WebUIRequestHandlerBase { - private static readonly string[] resourcePath = new[] { "/{0}/api/v1/contentTypes" }; + private static readonly string[] resourcePath = new[] { "/{0}/api/v1/rulesets" }; private readonly IRulesEngine rulesEngine; private readonly IRuleStatusDtoAnalyzer ruleStatusDtoAnalyzer; - public GetContentTypeHandler(IRulesEngine rulesEngine, + public GetRulesetsHandler(IRulesEngine rulesEngine, IRuleStatusDtoAnalyzer ruleStatusDtoAnalyzer, WebUIOptions webUIOptions) : base(resourcePath, webUIOptions) { @@ -29,29 +29,29 @@ protected override async Task HandleRequestAsync(HttpRequest httpRequest, HttpRe { try { - var contents = await this.rulesEngine.GetContentTypesAsync().ConfigureAwait(false); + var rulesets = await this.rulesEngine.GetRulesetsAsync().ConfigureAwait(false); - var contentTypes = new List(); + var rulesetDtos = new List(); var index = 0; - foreach (var identifier in contents) + foreach (var ruleset in rulesets) { - var genericRules = await this.rulesEngine - .SearchAsync(new SearchArgs(identifier, + var rules = await this.rulesEngine + .SearchAsync(new SearchArgs(ruleset.Name, DateTime.MinValue, DateTime.MaxValue)) .ConfigureAwait(false); - contentTypes.Add(new ContentTypeDto + rulesetDtos.Add(new RulesetDto { Index = index, - Name = identifier, - ActiveRulesCount = genericRules.Count(IsActive), - RulesCount = genericRules.Count() + Name = ruleset.Name, + ActiveRulesCount = rules.Count(IsActive), + RulesCount = rules.Count() }); index++; } - await this.WriteResponseAsync(httpResponse, contentTypes, (int)HttpStatusCode.OK).ConfigureAwait(false); + await this.WriteResponseAsync(httpResponse, rulesetDtos, (int)HttpStatusCode.OK).ConfigureAwait(false); } catch (Exception ex) { diff --git a/src/Rules.Framework.WebUI/WebUIApplicationBuilderExtensions.cs b/src/Rules.Framework.WebUI/WebUIApplicationBuilderExtensions.cs index 4e8bcea3..1cbc5455 100644 --- a/src/Rules.Framework.WebUI/WebUIApplicationBuilderExtensions.cs +++ b/src/Rules.Framework.WebUI/WebUIApplicationBuilderExtensions.cs @@ -9,7 +9,7 @@ namespace Rules.Framework.WebUI using Rules.Framework.WebUI.Handlers; /// - /// IApplicationBuilder extension for Rules Framework Web UI + /// extension for Rules Framework Web UI /// public static class WebUIApplicationBuilderExtensions { @@ -17,14 +17,15 @@ public static class WebUIApplicationBuilderExtensions /// Uses the rules framework web UI. /// /// The application. - /// The generic rules engine factory. + /// The rules engine factory. /// The web UI options action. /// - public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilder app, - Func genericRulesEngineFactory, + public static IApplicationBuilder UseRulesFrameworkWebUI( + this IApplicationBuilder app, + Func rulesEngineFactory, Action webUIOptionsAction) { - var genericRulesEngine = genericRulesEngineFactory.Invoke(app.ApplicationServices); + var genericRulesEngine = rulesEngineFactory.Invoke(app.ApplicationServices); return app.UseRulesFrameworkWebUI(genericRulesEngine, webUIOptionsAction); } @@ -32,35 +33,38 @@ public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilde /// Uses the rules framework web UI. /// /// The application. - /// The generic rules engine factory. + /// The rules engine factory. /// - public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilder app, - Func genericRulesEngineFactory) + public static IApplicationBuilder UseRulesFrameworkWebUI( + this IApplicationBuilder app, + Func rulesEngineFactory) { - return app.UseRulesFrameworkWebUI(genericRulesEngineFactory, null); + return app.UseRulesFrameworkWebUI(rulesEngineFactory, null); } /// /// Uses the rules framework web UI. /// /// The application. - /// The generic rules engine. + /// The rules engine. /// - public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilder app, - IRulesEngine genericRulesEngine) + public static IApplicationBuilder UseRulesFrameworkWebUI( + this IApplicationBuilder app, + IRulesEngine rulesEngine) { - return app.UseRulesFrameworkWebUI(genericRulesEngine, new WebUIOptions()); + return app.UseRulesFrameworkWebUI(rulesEngine, new WebUIOptions()); } /// /// Uses the rules framework web UI. /// /// The application. - /// The generic rules engine. + /// The rules engine. /// The web UI options action. /// - public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilder app, - IRulesEngine genericRulesEngine, + public static IApplicationBuilder UseRulesFrameworkWebUI( + this IApplicationBuilder app, + IRulesEngine rulesEngine, Action webUIOptionsAction) { WebUIOptions webUIOptions; @@ -71,17 +75,19 @@ public static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilde webUIOptionsAction?.Invoke(webUIOptions); } - return app.UseRulesFrameworkWebUI(genericRulesEngine, webUIOptions); + return app.UseRulesFrameworkWebUI(rulesEngine, webUIOptions); } /// /// Uses the rules framework web UI. /// /// The application. - /// The generic rules engine. + /// The rules engine. /// The web UI options. /// - private static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuilder app, IRulesEngine genericRulesEngine, + private static IApplicationBuilder UseRulesFrameworkWebUI( + this IApplicationBuilder app, + IRulesEngine rulesEngine, WebUIOptions webUIOptions) { var ruleStatusDtoAnalyzer = new RuleStatusDtoAnalyzer(); @@ -90,9 +96,9 @@ private static IApplicationBuilder UseRulesFrameworkWebUI(this IApplicationBuild new List { new GetIndexPageHandler(webUIOptions), - new GetConfigurationsHandler(genericRulesEngine, webUIOptions), - new GetContentTypeHandler(genericRulesEngine, ruleStatusDtoAnalyzer, webUIOptions), - new GetRulesHandler(genericRulesEngine, ruleStatusDtoAnalyzer, webUIOptions) + new GetConfigurationsHandler(rulesEngine, webUIOptions), + new GetRulesetsHandler(rulesEngine, ruleStatusDtoAnalyzer, webUIOptions), + new GetRulesHandler(rulesEngine, ruleStatusDtoAnalyzer, webUIOptions) }, webUIOptions); diff --git a/src/Rules.Framework.WebUI/index.html b/src/Rules.Framework.WebUI/index.html index 13fe9a1d..76b8b047 100644 --- a/src/Rules.Framework.WebUI/index.html +++ b/src/Rules.Framework.WebUI/index.html @@ -73,8 +73,8 @@