Skip to content

Commit 5606a30

Browse files
authored
Fix issue in dates used in rules matching (#123)
* Changed namespace of Scenarios test and added test for rules matching * minor changes * Refactored test * fixed issue with rules * Completed tests * Fixed dates in rulesframework and typo in priorityCriteria * Set dates parameters in matchasync as full datettimes * Changed tests to include also datetime during the day * changes test names * small change * Re-added PriotityCriteria as obsolete * replaced explicit types by implicit types in tests * added obsolete method to irulesengineoptions * minor changes * more replacement of explicit variables by var * Made references to projects within solution to be made all by project reference * removed dotnet-build step to replace packages by projects * Completed last commit * Moved Providers.InMemory namespace to Rules.Framework assembly * removed License.MD link * fixed based on codacy analysis * dumb commit * Deleted stuff * fixed mongodb csproj file * fixed issues pointed by codacy analysis * attempt to fix codacy issues * minor changes * Changed get and set for obsolete PriotityCriteria
1 parent 21a02ee commit 5606a30

64 files changed

Lines changed: 905 additions & 497 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

samples/Rules.Framework.InMemory.Sample/Engine/RulesEngineProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public RulesEngineProvider(RulesBuilder rulesBuilder)
1919
.WithContentType<ContentTypes>()
2020
.WithConditionType<ConditionTypes>()
2121
.SetInMemoryDataSource()
22-
.Configure(c => c.PriotityCriteria = PriorityCriterias.BottommostRuleWins)
22+
.Configure(opt => opt.PriorityCriteria = PriorityCriterias.BottommostRuleWins)
2323
.Build();
2424

2525
await rulesBuilder.BuildAsync(rulesEngine).ConfigureAwait(false);

src/Rules.Framework.Providers.MongoDb/MongoDbProviderRulesDataSource.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Rules.Framework.Providers.MongoDb
1313
/// </summary>
1414
/// <typeparam name="TContentType">The type of the content type.</typeparam>
1515
/// <typeparam name="TConditionType">The type of the condition type.</typeparam>
16-
/// <seealso cref="Rules.Framework.IRulesDataSource{TContentType, TConditionType}" />
16+
/// <seealso cref="Rules.Framework.IRulesDataSource{TContentType, TConditionType}"/>
1717
public class MongoDbProviderRulesDataSource<TContentType, TConditionType> : IRulesDataSource<TContentType, TConditionType>
1818
{
1919
private readonly IMongoDatabase mongoDatabase;
@@ -49,7 +49,8 @@ public async Task AddRuleAsync(Rule<TContentType, TConditionType> rule)
4949
}
5050

5151
/// <summary>
52-
/// Gets the rules categorized with specified <paramref name="contentType" /> between <paramref name="dateBegin" /> and <paramref name="dateEnd" />.
52+
/// Gets the rules categorized with specified <paramref name="contentType"/> between
53+
/// <paramref name="dateBegin"/> and <paramref name="dateEnd"/>.
5354
/// </summary>
5455
/// <param name="contentType">the content type categorization.</param>
5556
/// <param name="dateBegin">the filtering begin date.</param>
@@ -113,25 +114,14 @@ private static FilterDefinition<RuleDataModel> BuildFilterByContentTypeAndDatesI
113114
{
114115
var contentTypeFilter = Builders<RuleDataModel>.Filter.Eq(x => x.ContentType, contentType.ToString());
115116

116-
// To fetch rules that begin during filtered interval but end after it.
117-
var dateBeginFilter = Builders<RuleDataModel>.Filter.And(
118-
Builders<RuleDataModel>.Filter.Gte(x => x.DateBegin, dateBegin),
119-
Builders<RuleDataModel>.Filter.Lt(x => x.DateBegin, dateEnd));
120-
121-
// To fetch rules that begun before filtered interval but end during it.
122-
var dateEndFilter = Builders<RuleDataModel>.Filter.And(
123-
Builders<RuleDataModel>.Filter.Ne(x => x.DateEnd, null),
124-
Builders<RuleDataModel>.Filter.Gte(x => x.DateEnd, dateBegin),
125-
Builders<RuleDataModel>.Filter.Lt(x => x.DateEnd, dateEnd));
126-
127-
// To fetch rules that begun before and end after filtered interval.
128-
var slicingFilter = Builders<RuleDataModel>.Filter.And(
129-
Builders<RuleDataModel>.Filter.Lt(x => x.DateBegin, dateBegin),
117+
var datesFilter = Builders<RuleDataModel>.Filter.And(
118+
Builders<RuleDataModel>.Filter.Lte(rule => rule.DateBegin, dateEnd),
130119
Builders<RuleDataModel>.Filter.Or(
131-
Builders<RuleDataModel>.Filter.Eq(x => x.DateEnd, null),
132-
Builders<RuleDataModel>.Filter.Gt(x => x.DateEnd, dateEnd)));
120+
Builders<RuleDataModel>.Filter.Gt(rule => rule.DateEnd, dateBegin),
121+
Builders<RuleDataModel>.Filter.Eq(rule => rule.DateEnd, null))
122+
);
133123

134-
return Builders<RuleDataModel>.Filter.And(contentTypeFilter, Builders<RuleDataModel>.Filter.Or(dateBeginFilter, dateEndFilter, slicingFilter));
124+
return Builders<RuleDataModel>.Filter.And(contentTypeFilter, datesFilter);
135125
}
136126

137127
private static FilterDefinition<RuleDataModel> BuildFilterFromRulesFilterArgs(RulesFilterArgs<TContentType> rulesFilterArgs)

src/Rules.Framework.Providers.MongoDb/Rules.Framework.Providers.MongoDb.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
4040
</ItemGroup>
4141

42-
<ItemGroup>
43-
<ProjectReference Include="..\Rules.Framework\Rules.Framework.csproj" />
44-
</ItemGroup>
42+
<ItemGroup>
43+
<ProjectReference Include="..\Rules.Framework\Rules.Framework.csproj" />
44+
</ItemGroup>
4545
</Project>

src/Rules.Framework/IRulesEngineOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace Rules.Framework
22
{
3+
using System;
34
using System.Collections.Generic;
45
using Rules.Framework.Core;
56

@@ -22,6 +23,12 @@ public interface IRulesEngineOptions
2223
/// <summary>
2324
/// Gets the priority criteria to untie when multiples rules are matched.
2425
/// </summary>
26+
[Obsolete("This property has a typo and has been replaced by PriorityCriteria.")]
2527
public PriorityCriterias PriotityCriteria { get; }
28+
29+
/// <summary>
30+
/// Gets the priority criteria to untie when multiples rules are matched.
31+
/// </summary>
32+
public PriorityCriterias PriorityCriteria { get; }
2633
}
2734
}

src/Rules.Framework/Providers/InMemory/InMemoryProviderRulesDataSource.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ public Task<IEnumerable<Rule<TContentType, TConditionType>>> GetRulesAsync(TCont
5959
{
6060
return Task.Run(() =>
6161
{
62-
IEnumerable<RuleDataModel<TContentType, TConditionType>> ruleDataModels = this.inMemoryRulesStorage.GetRulesBy(contentType);
62+
var filteredByContent = this.inMemoryRulesStorage.GetRulesBy(contentType);
6363

64-
IEnumerable<RuleDataModel<TContentType, TConditionType>> filteredByDate = ruleDataModels.Where(r =>
65-
(r.DateBegin >= dateBegin && r.DateBegin < dateEnd)
66-
|| (!(r.DateEnd is null) && r.DateEnd >= dateBegin && r.DateEnd < dateEnd)
67-
|| (r.DateBegin < dateBegin && (r.DateEnd is null || r.DateEnd > dateEnd)));
64+
var filteredByDate = filteredByContent.Where(rule =>
65+
rule.DateBegin <= dateEnd
66+
&& (rule.DateEnd is null || rule.DateEnd > dateBegin)
67+
);
6868

6969
return filteredByDate.Select(r => this.ruleFactory.CreateRule(r)).AsEnumerable();
7070
});

src/Rules.Framework/Rules.Framework.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
</PropertyGroup>
2626

2727
<ItemGroup>
28-
<None Include="..\..\LICENSE.md">
28+
<None Include="..\..\LICENSE.md" >
2929
<Pack>True</Pack>
3030
<PackagePath></PackagePath>
3131
</None>

src/Rules.Framework/RulesEngine.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public Task<RuleOperationResult> AddRuleAsync(Rule<TContentType, TConditionType>
7474
/// <returns>Rules engine priority criterias</returns>
7575
public PriorityCriterias GetPriorityCriteria()
7676
{
77-
return this.rulesEngineOptions.PriotityCriteria;
77+
return this.rulesEngineOptions.PriorityCriteria;
7878
}
7979

8080
/// <summary>
@@ -128,8 +128,8 @@ public Task<IEnumerable<Rule<TContentType, TConditionType>>> MatchManyAsync(TCon
128128
MatchMode = MatchModes.Exact,
129129
};
130130

131-
var dateBegin = matchDateTime.Date;
132-
var dateEnd = matchDateTime.Date.AddDays(1);
131+
var dateBegin = matchDateTime;
132+
var dateEnd = matchDateTime;
133133

134134
return this.MatchAsync(contentType, dateBegin, dateEnd, conditions, evaluationOptions);
135135
}
@@ -203,11 +203,6 @@ public async Task<IEnumerable<Rule<TContentType, TConditionType>>> SearchAsync(S
203203
MatchMode = MatchModes.Search,
204204
};
205205

206-
if (dateBegin == dateEnd)
207-
{
208-
dateEnd = dateBegin.AddDays(1);
209-
}
210-
211206
return await this.MatchAsync(searchArgs.ContentType, dateBegin, dateEnd, searchArgs.Conditions, evaluationOptions).ConfigureAwait(false);
212207
}
213208

@@ -372,7 +367,7 @@ private async Task<IEnumerable<Rule<TContentType, TConditionType>>> MatchAsync(
372367

373368
private Rule<TContentType, TConditionType> SelectRuleByPriorityCriteria(IEnumerable<Rule<TContentType, TConditionType>> rules)
374369
{
375-
return this.rulesEngineOptions.PriotityCriteria == PriorityCriterias.BottommostRuleWins
370+
return this.rulesEngineOptions.PriorityCriteria == PriorityCriterias.BottommostRuleWins
376371
? rules.OrderByDescending(r => r.Priority).First()
377372
: rules.OrderBy(r => r.Priority).First();
378373
}

src/Rules.Framework/RulesEngineOptions.cs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace Rules.Framework
22
{
3+
using System;
34
using System.Collections.Generic;
45
using System.Linq;
56
using Rules.Framework.Core;
@@ -14,6 +15,38 @@ private RulesEngineOptions()
1415
this.DataTypeDefaults = new Dictionary<DataTypes, object>();
1516
}
1617

18+
/// <summary>
19+
/// Gets the default values for each of the supported data types.
20+
/// </summary>
21+
public IDictionary<DataTypes, object> DataTypeDefaults { get; }
22+
23+
/// <summary>
24+
/// <para>
25+
/// Gets or sets the rules engine behavior when no condition with a specific type is
26+
/// provided to rules engine to match with a rule's condition with the same type.
27+
/// </para>
28+
/// <para>
29+
/// e.g. a rule with a condition of type "Age" is under evaluation but no condition of type
30+
/// "Age" was supplied.
31+
/// </para>
32+
/// </summary>
33+
public MissingConditionBehaviors MissingConditionBehavior { get; set; }
34+
35+
/// <summary>
36+
/// Gets or sets the priority criteria to untie when multiples rules are matched.
37+
/// </summary>
38+
public PriorityCriterias PriorityCriteria { get; set; }
39+
40+
/// <summary>
41+
/// Gets or sets the priority criteria to untie when multiples rules are matched.
42+
/// </summary>
43+
[Obsolete("This property has a typo and has been replaced by PriorityCriteria.")]
44+
public PriorityCriterias PriotityCriteria
45+
{
46+
get { return this.PriorityCriteria; }
47+
set { this.PriorityCriteria = value; }
48+
}
49+
1750
/// <summary>
1851
/// Creates a new set of rules engine options with framework-configured defaults.
1952
/// </summary>
@@ -31,7 +64,7 @@ public static RulesEngineOptions NewWithDefaults()
3164
RulesEngineOptions rulesEngineOptions = new RulesEngineOptions
3265
{
3366
MissingConditionBehavior = MissingConditionBehaviors.UseDataTypeDefault,
34-
PriotityCriteria = PriorityCriterias.TopmostRuleWins
67+
PriorityCriteria = PriorityCriterias.TopmostRuleWins
3568
};
3669

3770
rulesEngineOptions.DataTypeDefaults[DataTypes.Boolean] = default(bool);
@@ -46,21 +79,5 @@ public static RulesEngineOptions NewWithDefaults()
4679

4780
return rulesEngineOptions;
4881
}
49-
50-
/// <summary>
51-
/// Gets the default values for each of the supported data types.
52-
/// </summary>
53-
public IDictionary<DataTypes, object> DataTypeDefaults { get; }
54-
55-
/// <summary>
56-
/// <para>Gets or sets the rules engine behavior when no condition with a specific type is provided to rules engine to match with a rule's condition with the same type.</para>
57-
/// <para>e.g. a rule with a condition of type "Age" is under evaluation but no condition of type "Age" was supplied.</para>
58-
/// </summary>
59-
public MissingConditionBehaviors MissingConditionBehavior { get; set; }
60-
61-
/// <summary>
62-
/// Gets or sets the priority criteria to untie when multiples rules are matched.
63-
/// </summary>
64-
public PriorityCriterias PriotityCriteria { get; set; }
6582
}
6683
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Rules.Framework.IntegrationTests.Common.Features
2+
{
3+
using Rules.Framework.Core;
4+
using Rules.Framework.Tests.Stubs;
5+
6+
public class RuleSpecification
7+
{
8+
public RuleSpecification(Rule<ContentType, ConditionType> ruleBuilderResult, RuleAddPriorityOption ruleAddPriorityOption)
9+
{
10+
this.Rule = ruleBuilderResult;
11+
this.RuleAddPriorityOption = ruleAddPriorityOption;
12+
}
13+
14+
public RuleAddPriorityOption RuleAddPriorityOption { get; set; }
15+
16+
public Rule<ContentType, ConditionType> Rule { get; set; }
17+
}
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Rules.Framework.Tests.Stubs
2+
{
3+
public enum ConditionType
4+
{
5+
ConditionType1 = 1,
6+
7+
ConditionType2 = 2,
8+
9+
ConditionType3 = 3
10+
}
11+
}

0 commit comments

Comments
 (0)