Skip to content

Commit

Permalink
feat: create non generic rules engine (#169)
Browse files Browse the repository at this point in the history
* refactor!: create non-generic rules engine

* chore: change var style rules for C#

* feat!: add APIs to create content types

* chore: resolve codacy code analysis issues

* chore: resolve codacy code analysis issues #2
  • Loading branch information
luispfgarces authored Sep 24, 2024
1 parent b0de99a commit c9213a0
Show file tree
Hide file tree
Showing 310 changed files with 5,481 additions and 3,976 deletions.
7 changes: 4 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ dotnet_code_quality_unused_parameters = all:suggestion
#### C# Coding Conventions ####

# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
csharp_style_var_elsewhere = true:silent
csharp_style_var_for_built_in_types = true:silent
csharp_style_var_when_type_is_apparent = true:silent

# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
Expand Down Expand Up @@ -231,6 +231,7 @@ dotnet_style_namespace_match_folder = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_primary_constructors = true:suggestion

[*.vb]
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion:suggestion
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
namespace Rules.Framework.InMemory.Sample.Engine
{
using System.Collections.Generic;
using global::Rules.Framework.InMemory.Sample.Enums;

internal interface IContentTypes
{
ContentTypes ContentType { get; }

IEnumerable<RuleSpecification> GetRulesSpecifications();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Rules.Framework.InMemory.Sample.Engine
{
using global::Rules.Framework;
using global::Rules.Framework.Builder;
using global::Rules.Framework.Builder.Generic;
using global::Rules.Framework.InMemory.Sample.Enums;

internal class RuleSpecification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ namespace Rules.Framework.InMemory.Sample.Engine
{
using System.Collections.Generic;
using System.Threading.Tasks;
using global::Rules.Framework.InMemory.Sample.Enums;
using global::Rules.Framework.InMemory.Sample.Exceptions;

internal class RulesBuilder
Expand All @@ -11,10 +10,12 @@ internal class RulesBuilder

public RulesBuilder(IEnumerable<IContentTypes> contentTypes) => this.contentTypes = contentTypes;

public async Task BuildAsync(RulesEngine<ContentTypes, ConditionTypes> rulesEngine)
public async Task BuildAsync(IRulesEngine rulesEngine)
{
foreach (var contentType in contentTypes)
{
await rulesEngine.CreateContentTypeAsync(contentType.ContentType.ToString());

var rulesSpecifications = contentType.GetRulesSpecifications();

foreach (var ruleSpecification in rulesSpecifications)
Expand All @@ -28,7 +29,7 @@ public async Task BuildAsync(RulesEngine<ContentTypes, ConditionTypes> rulesEngi
.AddRuleAsync(
ruleSpecification.RuleBuilderResult.Rule,
ruleSpecification.RuleAddPriorityOption
).ConfigureAwait(false);
);

if (!ruleOperationResult.IsSuccess)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,17 @@ namespace Rules.Framework.InMemory.Sample.Engine
using System;
using System.Threading;
using System.Threading.Tasks;
using global::Rules.Framework.InMemory.Sample.Enums;
using global::Rules.Framework.Providers.InMemory;

internal class RulesEngineProvider
{
private readonly Lazy<Task<RulesEngine<ContentTypes, ConditionTypes>>> lazyRulesEngine;
private readonly Lazy<Task<IRulesEngine>> lazyRulesEngine;

public RulesEngineProvider(RulesBuilder rulesBuilder)
{
lazyRulesEngine = new Lazy<Task<RulesEngine<ContentTypes, ConditionTypes>>>(async () =>
lazyRulesEngine = new Lazy<Task<IRulesEngine>>(async () =>
{
var rulesEngine = RulesEngineBuilder
.CreateRulesEngine()
.WithContentType<ContentTypes>()
.WithConditionType<ConditionTypes>()
.SetInMemoryDataSource()
.Configure(opt => opt.PriorityCriteria = PriorityCriterias.BottommostRuleWins)
.Build();
Expand All @@ -28,7 +24,7 @@ public RulesEngineProvider(RulesBuilder rulesBuilder)
}, LazyThreadSafetyMode.ExecutionAndPublication);
}

public Task<RulesEngine<ContentTypes, ConditionTypes>> GetRulesEngineAsync()
public Task<IRulesEngine> GetRulesEngineAsync()
=> lazyRulesEngine.Value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public async Task<T> MatchOneAsync<T>(
.ConfigureAwait(false);

var match = await rulesEngine
.MakeGeneric<ContentTypes, ConditionTypes>()
.MatchOneAsync(contentType, dateTime, rulesConditions)
.ConfigureAwait(false);

Expand Down
17 changes: 6 additions & 11 deletions samples/Rules.Framework.InMemory.Sample/Rules/TestNumberRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ namespace Rules.Framework.InMemory.Sample.Rules
{
using System;
using System.Collections.Generic;
using global::Rules.Framework.Builder;
using global::Rules.Framework.Core;
using global::Rules.Framework.Builder.Generic;
using global::Rules.Framework.InMemory.Sample.Engine;
using global::Rules.Framework.InMemory.Sample.Enums;

Expand All @@ -16,6 +15,8 @@ public TestNumberRules()
this.rulesSpecifications = new List<RuleSpecification>();
}

public ContentTypes ContentType => ContentTypes.TestNumber;

public IEnumerable<RuleSpecification> GetRulesSpecifications()
{
Add(CreateRuleForCoolNumbers(), RuleAddPriorityOption.ByPriorityNumber(3));
Expand All @@ -34,17 +35,13 @@ private void Add(
RuleAddPriorityOption = ruleAddPriorityOption,
});

private RuleBuilderResult<ContentTypes, ConditionTypes> CreateDefaultRule() =>
RuleBuilder
.NewRule<ContentTypes, ConditionTypes>()
private RuleBuilderResult<ContentTypes, ConditionTypes> CreateDefaultRule() => Rule.New<ContentTypes, ConditionTypes>()
.WithName("Default rule for test number")
.WithContent(ContentTypes.TestNumber, ":| default nothing special about this number")
.WithDateBegin(new DateTime(2019, 01, 01))
.Build();

private RuleBuilderResult<ContentTypes, ConditionTypes> CreateRuleForCoolNumbers() =>
RuleBuilder
.NewRule<ContentTypes, ConditionTypes>()
private RuleBuilderResult<ContentTypes, ConditionTypes> CreateRuleForCoolNumbers() => Rule.New<ContentTypes, ConditionTypes>()
.WithName("Rule for cool numbers")
.WithContent(ContentTypes.TestNumber, ":D this number is so COOL!")
.WithDateBegin(new DateTime(2019, 01, 01))
Expand All @@ -56,9 +53,7 @@ private RuleBuilderResult<ContentTypes, ConditionTypes> CreateRuleForCoolNumbers
.Value(ConditionTypes.SumAll, Operators.StartsWith, "5"))))
.Build();

private RuleBuilderResult<ContentTypes, ConditionTypes> CreateRuleForSosoNumbers() =>
RuleBuilder
.NewRule<ContentTypes, ConditionTypes>()
private RuleBuilderResult<ContentTypes, ConditionTypes> CreateRuleForSosoNumbers() => Rule.New<ContentTypes, ConditionTypes>()
.WithName("Rule for so so numbers")
.WithContent(ContentTypes.TestNumber, ":) this number is so so")
.WithDateBegin(new DateTime(2019, 01, 01))
Expand Down
3 changes: 3 additions & 0 deletions samples/Rules.Framework.WebUI.Sample/Engine/IContentTypes.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
namespace Rules.Framework.WebUI.Sample.Engine
{
using System.Collections.Generic;
using global::Rules.Framework.WebUI.Sample.Enums;

internal interface IContentTypes
{
ContentTypes[] ContentTypes { get; }

IEnumerable<RuleSpecification> GetRulesSpecifications();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Rules.Framework.WebUI.Sample.Engine
{
using global::Rules.Framework;
using global::Rules.Framework.Builder;
using global::Rules.Framework.Builder.Generic;
using global::Rules.Framework.WebUI.Sample.Enums;

internal sealed class RuleSpecification : RuleSpecificationBase<ContentTypes, ConditionTypes>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Rules.Framework.WebUI.Sample.Engine
{
using global::Rules.Framework;
using global::Rules.Framework.Builder;
using global::Rules.Framework.Builder.Generic;

internal class RuleSpecificationBase<TContentType, TConditionType>
{
Expand Down
10 changes: 7 additions & 3 deletions samples/Rules.Framework.WebUI.Sample/Engine/RulesBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ namespace Rules.Framework.WebUI.Sample.Engine
{
using System.Collections.Generic;
using System.Threading.Tasks;
using global::Rules.Framework.WebUI.Sample.Enums;
using global::Rules.Framework.WebUI.Sample.Exceptions;

internal class RulesBuilder
Expand All @@ -11,10 +10,15 @@ internal class RulesBuilder

public RulesBuilder(IEnumerable<IContentTypes> contentTypes) => this.contentTypes = contentTypes;

public async Task BuildAsync(RulesEngine<ContentTypes, ConditionTypes> rulesEngine)
public async Task BuildAsync(IRulesEngine rulesEngine)
{
foreach (var contentType in contentTypes)
{
foreach (var contentTypeValue in contentType.ContentTypes)
{
await rulesEngine.CreateContentTypeAsync(contentTypeValue.ToString());
}

var rulesSpecifications = contentType.GetRulesSpecifications();

foreach (var ruleSpecification in rulesSpecifications)
Expand All @@ -28,7 +32,7 @@ public async Task BuildAsync(RulesEngine<ContentTypes, ConditionTypes> rulesEngi
.AddRuleAsync(
ruleSpecification.RuleBuilderResult.Rule,
ruleSpecification.RuleAddPriorityOption
).ConfigureAwait(false);
);

if (!ruleOperationResult.IsSuccess)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@ namespace Rules.Framework.WebUI.Sample.Engine
using System;
using System.Threading;
using System.Threading.Tasks;
using global::Rules.Framework.WebUI.Sample.Enums;

internal class RulesEngineProvider
{
private readonly Lazy<Task<RulesEngine<ContentTypes, ConditionTypes>>> lazyRulesEngine;
private readonly Lazy<Task<IRulesEngine>> lazyRulesEngine;

public RulesEngineProvider(RulesBuilder rulesBuilder)
{
lazyRulesEngine = new Lazy<Task<RulesEngine<ContentTypes, ConditionTypes>>>(async () =>
lazyRulesEngine = new Lazy<Task<IRulesEngine>>(async () =>
{
var rulesEngine = RulesEngineBuilder
.CreateRulesEngine()
.WithContentType<ContentTypes>()
.WithConditionType<ConditionTypes>()
.SetInMemoryDataSource()
.Configure(c => c.PriorityCriteria = PriorityCriterias.TopmostRuleWins)
.Build();
Expand All @@ -27,7 +24,7 @@ public RulesEngineProvider(RulesBuilder rulesBuilder)
}, LazyThreadSafetyMode.ExecutionAndPublication);
}

public Task<RulesEngine<ContentTypes, ConditionTypes>> GetRulesEngineAsync()
public Task<IRulesEngine> GetRulesEngineAsync()
=> lazyRulesEngine.Value;
}
}
5 changes: 2 additions & 3 deletions samples/Rules.Framework.WebUI.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace Rules.Framework.WebUI.Sample
{
using global::Rules.Framework.Extension;
using global::Rules.Framework.WebUI.Sample.Engine;
using global::Rules.Framework.WebUI.Sample.ReadmeExample;
using global::Rules.Framework.WebUI.Sample.Rules;
Expand Down Expand Up @@ -46,7 +45,7 @@ private static void AddRulesFrameworkUI(IApplicationBuilder app, bool useReadmeE
{
if (useReadmeExample)
{
app.UseRulesFrameworkWebUI(new BasicRulesEngineExample().RulesEngine.CreateGenericEngine());
app.UseRulesFrameworkWebUI(new BasicRulesEngineExample().RulesEngine);

return;
}
Expand All @@ -62,7 +61,7 @@ private static void AddRulesFrameworkUI(IApplicationBuilder app, bool useReadmeE
.GetAwaiter()
.GetResult();

app.UseRulesFrameworkWebUI(rulesEngine.CreateGenericEngine());
app.UseRulesFrameworkWebUI(rulesEngine);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
namespace Rules.Framework.WebUI.Sample.ReadmeExample
{
using System;
using global::Rules.Framework.Core;
using global::Rules.Framework.Providers.InMemory;
using global::Rules.Framework.WebUI.Sample.Engine;

internal class BasicRulesEngineExample
Expand All @@ -11,8 +9,6 @@ public BasicRulesEngineExample()
{
this.RulesEngine = RulesEngineBuilder
.CreateRulesEngine()
.WithContentType<BasicContentType>()
.WithConditionType<BasicConditionType>()
.SetInMemoryDataSource()
.Configure(c => c.PriorityCriteria = PriorityCriterias.TopmostRuleWins)
.Build();
Expand All @@ -22,7 +18,7 @@ public BasicRulesEngineExample()
this.AddRules(rules);
}

public RulesEngine<BasicContentType, BasicConditionType> RulesEngine { get; }
public IRulesEngine RulesEngine { get; }

protected void AddRules(IEnumerable<RuleSpecificationBase<BasicContentType, BasicConditionType>> ruleSpecifications)
{
Expand All @@ -37,24 +33,21 @@ protected void AddRules(IEnumerable<RuleSpecificationBase<BasicContentType, Basi

private IEnumerable<RuleSpecificationBase<BasicContentType, BasicConditionType>> CreateRules()
{
var ruleForPremiumFreeSampleJanuary = RuleBuilder
.NewRule<BasicContentType, BasicConditionType>()
var ruleForPremiumFreeSampleJanuary = Rule.New<BasicContentType, BasicConditionType>()
.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))
.Build();

var ruleForPremiumFreeSampleApril = RuleBuilder
.NewRule<BasicContentType, BasicConditionType>()
var ruleForPremiumFreeSampleApril = Rule.New<BasicContentType, BasicConditionType>()
.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))
.Build();

var ruleForPremiumFreeSampleSeptember = RuleBuilder
.NewRule<BasicContentType, BasicConditionType>()
var ruleForPremiumFreeSampleSeptember = Rule.New<BasicContentType, BasicConditionType>()
.WithName("Rule for September sample for premium clients.")
.WithContent(BasicContentType.FreeSample, "ConditionerSample")
.WithCondition(BasicConditionType.ClientType, Operators.Equal, "Premium")
Expand Down
18 changes: 14 additions & 4 deletions samples/Rules.Framework.WebUI.Sample/Rules/RulesRandomFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ namespace Rules.Framework.WebUI.Sample.Rules
{
using System;
using System.Collections.Generic;
using global::Rules.Framework.Builder;
using global::Rules.Framework.Core;
using global::Rules.Framework.Builder.Generic;
using global::Rules.Framework.WebUI.Sample.Engine;
using global::Rules.Framework.WebUI.Sample.Enums;

Expand All @@ -18,6 +17,18 @@ public RulesRandomFactory()
this.random = new Random();
}

public ContentTypes[] ContentTypes => 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,
};

public IEnumerable<RuleSpecification> GetRulesSpecifications()
{
var currentYear = DateTime.UtcNow.Year;
Expand Down Expand Up @@ -49,8 +60,7 @@ private static RuleBuilderResult<ContentTypes, ConditionTypes> CreateMultipleRul
int value,
DateTime dateBegin,
DateTime? dateEnd,
bool isActive = true) => RuleBuilder
.NewRule<ContentTypes, ConditionTypes>()
bool isActive = true) => Rule.New<ContentTypes, ConditionTypes>()
.WithName($"Multi rule for test {contentTypes} {value}")
.WithContent(contentTypes, new { Value = value })
.WithDatesInterval(dateBegin, dateEnd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Rules.Framework.Providers.MongoDb.DataModel
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Options;
using Rules.Framework.Core;
using Rules.Framework;

[BsonKnownTypes(typeof(ComposedConditionNodeDataModel), typeof(ValueConditionNodeDataModel))]
internal class ConditionNodeDataModel
Expand Down
Loading

0 comments on commit c9213a0

Please sign in to comment.