Esempio n. 1
0
        public ParseResult Parse(string yaml)
        {
            _contentNodes = new List <ContentNode>();
            try
            {
                YamlRuleParser parser = new YamlRuleParser(yaml, null);
                _model = new Model.Model(parser.Header(), parser.Formulas().ToList(), parser.Tabellen().ToList(), parser.Flow().ToList());
                List <string> inclusiveSituations = null;
                foreach (var step in _model.Steps)
                {
                    if (step.IsSituational)
                    {
                        inclusiveSituations = step.Situation.Split(',')
                                              .Select(x => x.Trim())
                                              .Where(x => !string.IsNullOrWhiteSpace(x))
                                              .ToList();
                        foreach (var inclusiveSituation in inclusiveSituations)
                        {
                            var contentNodeStep = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}")
                            {
                                Parameter = new Parameter(step.Name, false, TypeEnum.Step, ref _model)
                            };
                            contentNodeStep.Parameter.SemanticKey = contentNodeStep.Name;
                            contentNodeStep.Situation             = inclusiveSituation;
                            _contentNodes.Add(contentNodeStep);
                            step.SemanticKey = contentNodeStep.Name;

                            if (step.Choices != null)
                            {
                                foreach (var choice in step.Choices)
                                {
                                    var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.{YamlRuleParser.StepChoice}.{choice.Situation}")
                                    {
                                        Parameter = new Parameter(choice.Situation, false, TypeEnum.Boolean, ref _model)
                                    };
                                    contentNode.Parameter.SemanticKey = contentNode.Name;
                                    contentNode.Situation             = inclusiveSituation;
                                    _contentNodes.Add(contentNode);
                                }
                            }

                            if (!string.IsNullOrEmpty(step.Value))
                            {
                                var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.{step.Value}");
                                contentNode.Parameter             = new Parameter(step.Name, null, TypeEnum.Double, ref _model);
                                contentNode.Parameter.SemanticKey = contentNode.Name;
                                contentNodeStep.Situation         = inclusiveSituation;
                                _contentNodes.Add(contentNode);
                            }

                            ResolveToQuestion(step.Formula, ref _contentNodes, step.Situation, step.Name);

                            if (step.Break != null && !string.IsNullOrEmpty(step.Break.Expression))
                            {
                                ContentNode node = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.geen_recht")
                                {
                                    IsBreak = true, IsSituational = step.IsSituational, Situation = inclusiveSituation, Parameter = new Parameter(name: "recht", value: null, type: TypeEnum.Boolean, model: ref _model)
                                };
                                step.Break.SemanticKey     = node.Name;
                                node.Parameter.SemanticKey = node.Name;
                                contentNodeStep.Situation  = inclusiveSituation;
                                _contentNodes.Add(node);
                            }
                        }
                    }
                    else
                    {
                        var contentNodeStep = new ContentNode($"{YamlRuleParser.Step}.{step.Name}")
                        {
                            Parameter = new Parameter(step.Name, false, TypeEnum.Step, ref _model)
                        };
                        contentNodeStep.Parameter.SemanticKey = contentNodeStep.Name;
                        _contentNodes.Add(contentNodeStep);
                        step.SemanticKey = contentNodeStep.Name;

                        if (step.Choices != null)
                        {
                            foreach (var choice in step.Choices)
                            {
                                var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepChoice}.{choice.Situation}")
                                {
                                    Parameter = new Parameter(choice.Situation, false, TypeEnum.Boolean, ref _model)
                                };
                                contentNode.Parameter.SemanticKey = contentNode.Name;
                                _contentNodes.Add(contentNode);
                            }
                        }
                        if (!string.IsNullOrEmpty(step.Value))
                        {
                            var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepValue}.{step.Value}");
                            contentNode.Parameter             = new Parameter(step.Name, null, TypeEnum.Double, ref _model);
                            contentNode.Parameter.SemanticKey = contentNode.Name;
                            _contentNodes.Add(contentNode);
                        }
                        ResolveToQuestion(step.Formula, ref _contentNodes, step.Situation, step.Name);

                        if (step.Break != null && !string.IsNullOrEmpty(step.Break.Expression))
                        {
                            step.Break.SemanticKey = string.Join('.', new[] { YamlRuleParser.Step, step.Name, "geen_recht" }.Where(s => !string.IsNullOrEmpty(s)));
                            ContentNode node = new ContentNode(step.Break.SemanticKey)
                            {
                                IsBreak = true, IsSituational = step.IsSituational, Situation = step.Situation, Parameter = new Parameter(name: "recht", value: null, type: TypeEnum.Boolean, model: ref _model)
                            };
                            node.Parameter.SemanticKey = step.Break.SemanticKey;
                            _contentNodes.Add(node);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var result = new ParseResult
                {
                    IsError = true,
                    Message = ex.Message
                };
                return(result);
            }
            ContentNodes.Add(new ContentNode("end")
            {
                Parameter = new Parameter("end", null, TypeEnum.Step, ref _model)
            });
            return(new ParseResult()
            {
                Message = Ok,
                ExpressionTree = new YamlDotNet.Serialization.Serializer().Serialize(_model),
                Model = _model
            });
        }
        private static Parameter Evaluate(FormulaExpressionContext caller, ref ExpressionContext context, ref Formula formula, ref ParametersCollection parameters1, QuestionDelegate onQuestion, ref Model.Model model)
        {
            if (parameters1 is null)
            {
                throw new ArgumentNullException(nameof(parameters1));
            }

            IDynamicExpression e = null;

            if (!formula.IsSituational)
            {
                try
                {
                    e = context.CompileDynamic(formula.Functions[0].Expression);
                    var       result = e.Evaluate().Infer();
                    Parameter parameter;
                    parameter = new Parameter(formula.Name, result.Infer(), null, ref model);
                    parameter.IsCalculated = true;
                    parameters1.Add(parameter);
                    if (context.Variables.ContainsKey(parameter.Name))
                    {
                        context.Variables.Remove(parameter.Name);
                    }
                    context.Variables.Add(parameter.Name, parameter.Value.Infer());
                    return(parameter);
                }
                catch (ExpressionCompileException)
                {
                    // Function can not evaluate further, before a Question/Answer sequence is fullfilled by the client.
                    throw new UnresolvedException($"Function {formula.Functions[0].Expression} can not evaluate further, before a Question/Answer sequence is fullfilled by the client.");
                }
            }
            else
            {
                foreach (var function in formula.Functions)
                {
                    foreach (var item in parameters1)
                    {
                        if (item.Name == function.Situation && (bool)item.Value == true)
                        {
                            try
                            {
                                e = context.CompileDynamic(function.Expression);
                                var parameter = new Parameter(formula.Name, e.Evaluate().Infer(), null, ref model);
                                parameter.IsCalculated = true;
                                parameters1.Add(parameter);
                                if (context.Variables.ContainsKey(parameter.Name))
                                {
                                    context.Variables.Remove(parameter.Name);
                                }
                                context.Variables.Add(parameter.Name, parameter.Value.Infer());
                                return(parameter);
                            }
                            catch (ExpressionCompileException)
                            {
                                // Function can not evaluate further, before a Question/Answer sequence is fullfilled by the client.
                                throw new UnresolvedException($"Function {function.Expression} can not evaluate further, before a Question/Answer sequence is fullfilled by the client.");
                            }
                        }
                    }
                }
                StringBuilder situations = new StringBuilder();
                var           parameters = new ParametersCollection();
                foreach (var function in formula.Functions)
                {
                    situations.Append(function.Situation + ",");
                    var parameter = new Parameter(function.Situation, TypeInference.Infer(function).Type, null, ref model);
                    parameters.Add(parameter);
                }
                if (onQuestion == null)
                {
                    throw new Exception($"In order to evaluate variable one of the following situations:  {situations.ToString().Trim(',')}, you need to provide a delegate callback to the client for providing an answer");
                }
                onQuestion(caller, new QuestionArgs("", parameters));
                // situation has to be formulated as an input parameter by the client.
                throw new UnresolvedException($"Can't evaluate formula {formula.Name} for situation. Please specify one of the following situations: {situations.ToString().Trim(',')}.");
            }
        }