private static bool AreAllSearchConditionsPresent(IConditionNode <TConditionType> conditionNode, IEnumerable <Condition <TConditionType> > conditions)
        {
            // Conditions checklist is a mere control construct to avoid a full sweep of the condition nodes tree when we already found all conditions.
            IDictionary <TConditionType, bool> conditionsChecklist = new Dictionary <TConditionType, bool>(conditions.ToDictionary(ks => ks.Type, vs => false));

            return(VisitConditionNode(conditionNode, conditionsChecklist));
        }
        private async Task <IConditionNode> CreateConditionNodeRecursive(Guid tenantId, CreateConditionNodeBase createConditionNodeBase)
        {
            switch (createConditionNodeBase)
            {
            case CreateComposedConditionNode cccn:
                LogicalOperatorCodes logicalOperatorCode = (LogicalOperatorCodes)cccn.LogicalOperatorCode;

                List <IConditionNode> conditionNodes = new List <IConditionNode>();
                foreach (CreateConditionNodeBase ccnb in cccn.ChildNodes)
                {
                    IConditionNode conditionNode = await this.CreateConditionNodeRecursive(tenantId, ccnb);

                    conditionNodes.Add(conditionNode);
                }

                return(this.conditionNodeAbstractFactory.CreateComposedConditionNode(logicalOperatorCode, conditionNodes));

            case CreateValueConditionNode cvcn:
                ConditionTypeKey conditionTypeKey = ConditionTypeKey.New(tenantId, cvcn.ConditionTypeCode);
                ConditionType    conditionType    = await this.conditionTypeRepository.GetById(conditionTypeKey);

                DataTypeCodes dataTypeCode = (DataTypeCodes)cvcn.DataTypeCode;
                OperatorCodes operatorCode = (OperatorCodes)cvcn.OperatorCode;

                return(this.conditionNodeAbstractFactory.CreateValueConditionNode(conditionType, dataTypeCode, operatorCode, cvcn.RightHandOperand));

            default:
                throw new NotSupportedException("Unsupported condition node creation.");
            }
        }
        private static bool VisitConditionNode(IConditionNode <TConditionType> conditionNode, IDictionary <TConditionType, bool> conditionsChecklist)
        {
            switch (conditionNode)
            {
            case IValueConditionNode <TConditionType> valueConditionNode:
                if (conditionsChecklist.ContainsKey(valueConditionNode.ConditionType))
                {
                    conditionsChecklist[valueConditionNode.ConditionType] = true;
                }

                return(conditionsChecklist.All(kvp => kvp.Value));

            case ComposedConditionNode <TConditionType> composedConditionNode:
                foreach (IConditionNode <TConditionType> childConditionNode in composedConditionNode.ChildConditionNodes)
                {
                    bool allPresentAlready = VisitConditionNode(childConditionNode, conditionsChecklist);
                    if (allPresentAlready)
                    {
                        return(true);
                    }
                }

                return(false);

            default:
                throw new NotSupportedException($"Unsupported condition node: '{conditionNode.GetType().Name}'.");
            }
        }
Exemple #4
0
        private ConditionNodeBaseDto ConvertNodeToDto(IConditionNode conditionNode)
        {
            switch (conditionNode)
            {
            case ComposedConditionNode ccn:
                return(new ComposedConditionNodeDto
                {
                    ChildNodes = ccn.ChildNodes.Select(cn => this.ConvertNodeToDto(cn)),
                    LogicalOperatorCode = ccn.LogicalOperatorCode.AsInteger()
                });

            case IValueConditionNode vcn:
                return(new ValueConditionNodeDto
                {
                    ConditionTypeCode = vcn.ConditionTypeCode,
                    DataTypeCode = vcn.DataTypeCode.AsInteger(),
                    LogicalOperatorCode = vcn.LogicalOperatorCode.AsInteger(),
                    OperatorCode = vcn.OperatorCode.AsInteger(),
                    RightHandOperand = vcn.GetRightHandOperandAsObject()
                });

            default:
                throw new NotSupportedException("Condition node type is not supported.");
            }
        }
        public async Task <RuleResult> CreateRule(CreateRule createRule)
        {
            RuleResult ruleResult = new RuleResult();

            IEnumerable <RuleValidationMessage> ruleValidationMessages = this.createRuleValidator.Validate(createRule);

            foreach (RuleValidationMessage validationMessage in ruleValidationMessages)
            {
                ruleResult.AddErrorMessage(validationMessage.Code, validationMessage.Message);
            }

            if (!ruleResult.HasErrors)
            {
                // Fetch content type and validate.
                ContentTypeKey contentTypeKey = ContentTypeKey.New(createRule.TenantId, createRule.ContentTypeCode);
                ContentType    contentType    = await this.contentTypeRepository.GetById(contentTypeKey);

                IConditionNode rootCondition = null;
                if (createRule.RootCondition != null)
                {
                    rootCondition = await this.CreateConditionNodeRecursive(createRule.TenantId, createRule.RootCondition);
                }

                CreateRuleArgs createRuleArgs = new CreateRuleArgs
                {
                    Content       = createRule.Content,
                    ContentType   = contentType,
                    DateBegin     = createRule.DateBegin,
                    DateEnd       = createRule.DateEnd,
                    Name          = createRule.Name,
                    Priority      = createRule.Priority,
                    RootCondition = rootCondition,
                    TenantId      = createRule.TenantId
                };

                Rule rule = this.ruleFactory.CreateRule(createRuleArgs);

                IEnumerable <Rule> existentRules = await this.ruleRepository.GetAll(
                    createRule.TenantId,
                    new RulesFilter
                {
                    ContentTypeCode = contentType.Key.Code
                },
                    null);

                // Move rules w/ priority >= to new rule's priority 1 value forward.
                foreach (Rule existentRule in existentRules.Where(r => r.Priority >= createRule.Priority))
                {
                    existentRule.Priority++;
                    await this.ruleRepository.Update(existentRule);
                }

                await this.ruleRepository.Add(rule);

                ruleResult.AffectedRule = rule;
            }

            return(ruleResult);
        }
Exemple #6
0
        public IComposedConditionNodeBuilder <TConditionType> AddCondition(Func <IConditionNodeBuilder <TConditionType>, IConditionNode <TConditionType> > addConditionFunc)
        {
            IConditionNode <TConditionType> conditionNode = addConditionFunc.Invoke(this.conditionNodeBuilder);

            this.conditions.Add(conditionNode);

            return(this);
        }
        public IRuleBuilder <TContentType, TConditionType> WithCondition(Func <IConditionNodeBuilder <TConditionType>, IConditionNode <TConditionType> > conditionFunc)
        {
            ConditionNodeBuilder <TConditionType> conditionNodeBuilder = new ConditionNodeBuilder <TConditionType>();

            IConditionNode <TConditionType> condition = conditionFunc.Invoke(conditionNodeBuilder);

            return(this.WithCondition(condition));
        }
        public bool Eval(IConditionNode <TConditionType> conditionNode, IEnumerable <Condition <TConditionType> > conditions, EvaluationOptions evaluationOptions)
        {
            if (evaluationOptions.ExcludeRulesWithoutSearchConditions && !AreAllSearchConditionsPresent(conditionNode, conditions))
            {
                return(false);
            }

            ISpecification <IEnumerable <Condition <TConditionType> > > specification = this.BuildSpecification(conditionNode, evaluationOptions.MatchMode);

            return(specification.IsSatisfiedBy(conditions));
        }
Exemple #9
0
 /// <summary>
 /// Register a conditional node.
 /// </summary>
 /// <param name="Node">Conditional node</param>
 public void Register(IConditionNode Node)
 {
     if (this.condition is null)
     {
         this.condition = Node;
     }
     else
     {
         throw new Exception("While construct already has a condition node defined.");
     }
 }
Exemple #10
0
        public void RootCondition_HavingSettedInstance_ReturnsProvidedInstance()
        {
            // Arrange
            Mock <IConditionNode <ConditionType> > mockConditionNode = new Mock <IConditionNode <ConditionType> >();
            IConditionNode <ConditionType>         expected          = mockConditionNode.Object;

            Rule <ContentType, ConditionType> sut = new Rule <ContentType, ConditionType>
            {
                RootCondition = expected
            };

            // Act
            IConditionNode <ConditionType> actual = sut.RootCondition;

            // Assert
            actual.Should().BeSameAs(expected);
        }
        public void ComposedConditionNode_Init_GivenSetupWithChildConditionsAndLogicalOperator_ReturnsSettedValues()
        {
            // Arrange
            LogicalOperators expectedLogicalOperator = LogicalOperators.Eval;
            IEnumerable <IConditionNode <ConditionType> > expectedChildConditionNodes = new IConditionNode <ConditionType>[]
            {
                new Mock <IConditionNode <ConditionType> >().Object,
                new Mock <IConditionNode <ConditionType> >().Object
            };

            ComposedConditionNode <ConditionType> sut = new ComposedConditionNode <ConditionType>(expectedLogicalOperator, expectedChildConditionNodes);

            // Act
            LogicalOperators actualLogicalOperator = sut.LogicalOperator;
            IEnumerable <IConditionNode <ConditionType> > actualChildConditionNodes = sut.ChildConditionNodes;

            // Assert
            actualLogicalOperator.Should().Be(expectedLogicalOperator);
            actualChildConditionNodes.Should().NotBeNull().And.BeSameAs(expectedChildConditionNodes);
        }
        public static void PerformValidation <TConditionType>(this IConditionNode <TConditionType> conditionNode, ConditionNodeValidationArgs <TConditionType> conditionNodeValidationArgs)
        {
            ValidationResult validationResult;

            switch (conditionNode)
            {
            case ComposedConditionNode <TConditionType> composedConditionNode:
                validationResult = conditionNodeValidationArgs.ComposedConditionNodeValidator.Validate(composedConditionNode);
                break;

            case IntegerConditionNode <TConditionType> integerConditionNode:
                validationResult = conditionNodeValidationArgs.IntegerConditionNodeValidator.Validate(integerConditionNode);
                break;

            case DecimalConditionNode <TConditionType> decimalConditionNode:
                validationResult = conditionNodeValidationArgs.DecimalConditionNodeValidator.Validate(decimalConditionNode);
                break;

            case StringConditionNode <TConditionType> stringConditionNode:
                validationResult = conditionNodeValidationArgs.StringConditionNodeValidator.Validate(stringConditionNode);
                break;

            case BooleanConditionNode <TConditionType> booleanConditionNode:
                validationResult = conditionNodeValidationArgs.BooleanConditionNodeValidator.Validate(booleanConditionNode);
                break;

            default:
                return;
            }

            if (!validationResult.IsValid)
            {
                foreach (ValidationFailure validationFailure in validationResult.Errors)
                {
                    conditionNodeValidationArgs.CustomContext.AddFailure(validationFailure);
                }
            }
        }
Exemple #13
0
 /// <summary>
 /// Register a conditional node.
 /// </summary>
 /// <param name="Node">Conditional node</param>
 public void Register(IConditionNode Node)
 {
     this.conditions.AddLast(Node);
 }
Exemple #14
0
 public virtual bool HasCondition(IConditionNode node)
 {
     return(conditionList_.Contains(node));
 }
Exemple #15
0
 public virtual void AddCondition(IConditionNode node)
 {
     conditionList_.Add(node);
 }
 private ISpecification <IEnumerable <Condition <TConditionType> > > BuildSpecification(IConditionNode <TConditionType> conditionNode, MatchModes matchMode)
 {
     return(conditionNode switch
     {
         IValueConditionNode <TConditionType> valueConditionNode => this.BuildSpecificationForValueNode(valueConditionNode, matchMode),
         ComposedConditionNode <TConditionType> composedConditionNode => this.BuildSpecificationForComposedNode(composedConditionNode, matchMode),
         _ => throw new NotSupportedException($"Unsupported condition node: '{conditionNode.GetType().Name}'."),
     });
Exemple #17
0
 public virtual void RemoveCondition(IConditionNode node)
 {
     conditionList_.Remove(node);
 }
Exemple #18
0
 /// <summary>
 /// 设置前提条件
 /// </summary>
 /// <param name="precondition"></param>
 public virtual void AddPrecondition(IConditionNode condition)
 {
     mCondition = condition;
 }
        public IRuleBuilder <TContentType, TConditionType> WithCondition(IConditionNode <TConditionType> condition)
        {
            this.rootCondition = condition;

            return(this);
        }