Skip to content

Commit 6396641

Browse files
authored
feat: added operator.NotIn for arrays
1 parent 6ecfc10 commit 6396641

6 files changed

Lines changed: 71 additions & 5 deletions

File tree

src/Rules.Framework/Builder/Validation/ValueConditionNodeValidator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,22 @@ public ValueConditionNodeValidator()
4949
.WithMessage(cn => $"Condition nodes with data type '{cn.DataType}' can't define a operator of type '{cn.Operator}'.");
5050

5151
this.RuleFor(c => c.Operator)
52-
.IsContainedOn(Operators.In)
52+
.IsContainedOn(Operators.In, Operators.NotIn, Operators.Equal, Operators.NotEqual)
5353
.When(c => c.DataType == DataTypes.ArrayString)
5454
.WithMessage(cn => $"Condition nodes with data type '{cn.DataType}' can't define a operator of type '{cn.Operator}'.");
5555

5656
this.RuleFor(c => c.Operator)
57-
.IsContainedOn(Operators.In)
57+
.IsContainedOn(Operators.In, Operators.NotIn, Operators.Equal, Operators.NotEqual)
5858
.When(c => c.DataType == DataTypes.ArrayInteger)
5959
.WithMessage(cn => $"Condition nodes with data type '{cn.DataType}' can't define a operator of type '{cn.Operator}'.");
6060

6161
this.RuleFor(c => c.Operator)
62-
.IsContainedOn(Operators.In)
62+
.IsContainedOn(Operators.In, Operators.NotIn, Operators.Equal, Operators.NotEqual)
6363
.When(c => c.DataType == DataTypes.ArrayDecimal)
6464
.WithMessage(cn => $"Condition nodes with data type '{cn.DataType}' can't define a operator of type '{cn.Operator}'.");
6565

6666
this.RuleFor(c => c.Operator)
67-
.IsContainedOn(Operators.In)
67+
.IsContainedOn(Operators.In, Operators.NotIn, Operators.Equal, Operators.NotEqual)
6868
.When(c => c.DataType == DataTypes.ArrayBoolean)
6969
.WithMessage(cn => $"Condition nodes with data type '{cn.DataType}' can't define a operator of type '{cn.Operator}'.");
7070
}

src/Rules.Framework/Core/Operators.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public enum Operators
7878
/// <summary>
7979
/// The not ends with operator.
8080
/// </summary>
81-
NotEndsWith = 15
81+
NotEndsWith = 15,
82+
83+
/// <summary>
84+
/// The not in operator.
85+
/// </summary>
86+
NotIn = 16,
8287
}
8388
}

src/Rules.Framework/Evaluation/OperatorsMetadata.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal static class OperatorsMetadata
2323
OperatorsMetadata.Contains,
2424
OperatorsMetadata.NotContains,
2525
OperatorsMetadata.In,
26+
OperatorsMetadata.NotIn,
2627
OperatorsMetadata.StartsWith,
2728
OperatorsMetadata.EndsWith,
2829
OperatorsMetadata.CaseInsensitiveStartsWith,
@@ -138,6 +139,12 @@ static OperatorsMetadata()
138139
SupportedMultiplicities = new[] { Multiplicities.OneToOne },
139140
};
140141

142+
public static OperatorMetadata NotIn => new()
143+
{
144+
Operator = Operators.NotIn,
145+
SupportedMultiplicities = new[] { Multiplicities.OneToMany },
146+
};
147+
141148
public static OperatorMetadata NotStartsWith => new()
142149
{
143150
Operator = Operators.NotStartsWith,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Rules.Framework.Evaluation.ValueEvaluation
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
internal sealed class NotInOperatorEvalStrategy : IOneToManyOperatorEvalStrategy
7+
{
8+
public bool Eval(object leftOperand, IEnumerable<object> rightOperand)
9+
=> !rightOperand.Contains(leftOperand);
10+
}
11+
}

src/Rules.Framework/Evaluation/ValueEvaluation/OperatorEvalStrategyFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public OperatorEvalStrategyFactory()
2121
{ Operators.Contains, new ContainsOperatorEvalStrategy() },
2222
{ Operators.NotContains, new NotContainsOperatorEvalStrategy() },
2323
{ Operators.In, new InOperatorEvalStrategy() },
24+
{ Operators.NotIn, new NotInOperatorEvalStrategy() },
2425
{ Operators.StartsWith, new StartsWithOperatorEvalStrategy() },
2526
{ Operators.EndsWith, new EndsWithOperatorEvalStrategy() },
2627
{ Operators.CaseInsensitiveStartsWith, new CaseInsensitiveStartsWithOperatorEvalStrategy() },
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace Rules.Framework.Tests.Evaluation.ValueEvaluation
2+
{
3+
using System.Linq;
4+
using FluentAssertions;
5+
using Rules.Framework.Evaluation.ValueEvaluation;
6+
using Xunit;
7+
8+
public class NotInOperatorEvalStrategyTests
9+
{
10+
[Fact]
11+
public void Eval_GivenInteger1AndCollectionContainingInteger1_ReturnsFalse()
12+
{
13+
// Arrange
14+
object leftOperand = 1;
15+
var rightOperand = Enumerable.Range(1, 3).Cast<object>();
16+
17+
var notInOperatorEvalStrategy = new NotInOperatorEvalStrategy();
18+
19+
// Act
20+
var result = notInOperatorEvalStrategy.Eval(leftOperand, rightOperand);
21+
22+
// Assert
23+
result.Should().BeFalse();
24+
}
25+
26+
[Fact]
27+
public void Eval_GivenInteger2AndCollectionNotContainingInteger2_ReturnsTrue()
28+
{
29+
// Arrange
30+
object leftOperand = 2;
31+
var rightOperand = Enumerable.Range(6, 3).Cast<object>();
32+
33+
var notInOperatorEvalStrategy = new NotInOperatorEvalStrategy();
34+
35+
// Act
36+
var result = notInOperatorEvalStrategy.Eval(leftOperand, rightOperand);
37+
38+
// Assert
39+
result.Should().BeTrue();
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)