Beispiel #1
0
        /// <summary>
        /// Builds the decision table definition
        /// </summary>
        /// <returns>Table decision definition built</returns>
        /// <exception cref="DmnBuilderException">Throws <see cref="DmnBuilderException"/> when the definition has already been built</exception>
        /// <exception cref="DmnBuilderException">Throws <see cref="DmnBuilderException"/> when there is no input, no output or no rule defined in builder</exception>
        protected internal override IDmnDecision Build()
        {
            if (IsBuilt)
            {
                throw Logger.Error <DmnBuilderException>("Decision is already built");
            }
            if (InputsInternal.Count < 1)
            {
                throw Logger.Error <DmnBuilderException>($"At least one input must be defined for decision table {Name}");
            }
            if (OutputsInternal.Count < 1)
            {
                throw Logger.Error <DmnBuilderException>($"At least one output must be defined for decision table {Name}");
            }
            if (RulesInternal.Count < 1)
            {
                throw Logger.Error <DmnBuilderException>($"At least one rule must be defined for decision table {Name}");
            }

            //create
            var tableDecision = new DmnDecisionTable(
                Name,
                HitPolicy,
                Aggregation,
                InputsInternal.Select(i => i.GetResultOrBuild()).ToArray(),
                OutputsInternal.Select(o => o.GetResultOrBuild()).ToArray(),
                RulesInternal.Select(r => r.GetResultOrBuild()).ToArray(),
                RequiredInputs.Select(i => Variables[i].GetResultOrBuild()).ToArray(),
                RequiredDecisions.Select(d => Decisions[d].GetResultOrBuild()).ToArray());

            ResultInternal = tableDecision;
            return(tableDecision);
        }
Beispiel #2
0
        /// <summary>
        /// Validates the <paramref name="sourceTable"/> within the <see cref="DmnModel"/>
        /// and creates <see cref="DmnDecisionTable"/>
        /// </summary>
        /// <param name="sourceTable">Decision source parsed from XML</param>
        /// <param name="decisionName">Unique name of decision</param>
        /// <param name="requiredInputs">Inputs required by decision</param>
        /// <param name="requiredDecisions">Decisions, the decision table depends on</param>
        ///<exception cref="ArgumentNullException"><paramref name="sourceTable"/>, <paramref name="decisionName"/>, <paramref name="requiredInputs"/> or <paramref name="requiredDecisions"/> is null.</exception>
        ///<exception cref="ArgumentException"><paramref name="decisionName"/> is empty</exception>
        /// <exception cref="DmnParserException">No outputs for decision table</exception>
        /// <exception cref="DmnParserException">No inputs for decision table</exception>
        /// <exception cref="DmnParserException">Input variable for decision table not found</exception>
        /// <exception cref="DmnParserException">No rules for decision table</exception>
        /// <exception cref="DmnParserException">Number of rule input entries doesn't match the number of inputs for decision table</exception>
        /// <exception cref="DmnParserException">Number of rule output entries doesn't match the number of outputs for decision table</exception>
        protected DmnDecisionTable CreateDecisionTable(
            DecisionTable sourceTable,
            string decisionName,
            List <IDmnVariable> requiredInputs,
            List <IDmnDecision> requiredDecisions)
        {
            if (sourceTable == null)
            {
                throw Logger.Fatal <ArgumentNullException>($"{nameof(sourceTable)} is null");
            }
            if (decisionName == null)
            {
                throw Logger.Fatal <ArgumentNullException>($"{nameof(decisionName)} is null");
            }
            if (string.IsNullOrWhiteSpace(decisionName))
            {
                throw Logger.Fatal <ArgumentException>($"{nameof(decisionName)} is empty");
            }
            if (requiredInputs == null)
            {
                throw Logger.Fatal <ArgumentNullException>($"{nameof(requiredInputs)} is null");
            }
            if (requiredDecisions == null)
            {
                throw Logger.Fatal <ArgumentNullException>($"{nameof(requiredDecisions)} is null");
            }

            //prepare outputs
            if (sourceTable.Outputs == null || sourceTable.Outputs.Count < 1)
            {
                throw Logger.Fatal <DmnParserException>($"No outputs for decision table {decisionName}");
            }

            var outputs   = new List <DmnDecisionTableOutput>();
            var outputIdx = 0;

            foreach (var sourceOutput in sourceTable.Outputs)
            {
                //Label, Name, Id
                var sourceVariableName =
                    !string.IsNullOrWhiteSpace(sourceOutput.Label) ? sourceOutput.Label :
                    !string.IsNullOrWhiteSpace(sourceOutput.Name) ? sourceOutput.Name :
                    sourceOutput.Id;

                var variableName = DmnVariableDefinition.NormalizeVariableName(sourceVariableName);
                if (!Variables.TryGetValue(variableName, out var variable))
                {
                    //create variable
                    variable = new DmnVariableDefinition(variableName);
                    Variables.Add(variableName, variable);
                }

                variable.AddValueSetter($"Table Decision {decisionName}");
                CheckAndUpdateVariableType(variable, sourceOutput.TypeRef);

                var allowedValues = sourceOutput.AllowedOutputValues?.Values;
                outputs.Add(new DmnDecisionTableOutput(outputIdx, variable, allowedValues));
                outputIdx++;
            }

            //prepare inputs
            if (sourceTable.Inputs == null || sourceTable.Inputs.Count < 1)
            {
                throw Logger.Fatal <DmnParserException>($"No inputs for decision table {decisionName}");
            }

            var inputs   = new List <DmnDecisionTableInput>();
            var inputIdx = 0;

            foreach (var sourceInput in sourceTable.Inputs)
            {
                //Expression or  variable by Label,  Id
                DmnVariableDefinition variable = null;
                string expression = null;

                if (string.IsNullOrWhiteSpace(sourceInput.InputExpression?.Text))
                {
                    var sourceVariableName = !string.IsNullOrWhiteSpace(sourceInput.Label) ? sourceInput.Label : sourceInput.Id;
                    var variableName       = DmnVariableDefinition.NormalizeVariableName(sourceVariableName);

                    if (!Variables.TryGetValue(variableName, out variable))
                    {
                        throw Logger.Fatal <DmnParserException>(
                                  $"Input variable {sourceVariableName} ({variableName}) for decision table {decisionName} not found");
                    }

                    CheckAndUpdateVariableType(variable, sourceInput.InputExpression?.TypeRef);
                }
                else
                {
                    expression = sourceInput.InputExpression.Text;
                }

                var allowedValues = sourceInput.AllowedInputValues?.Values;
                inputs.Add(new DmnDecisionTableInput(inputIdx, variable, expression, allowedValues));
                inputIdx++;
            }

            //prepare rules
            if (sourceTable.Rules == null || sourceTable.Rules.Count < 1)
            {
                throw Logger.Fatal <DmnParserException>($"No rules for decision table {decisionName}");
            }

            var rules   = new List <DmnDecisionTableRule>();
            var ruleIdx = 0;

            foreach (var sourceRule in sourceTable.Rules)
            {
                if (sourceRule.InputEntries == null || sourceRule.InputEntries.Count != inputs.Count)
                {
                    throw Logger.Fatal <DmnParserException>($"Number of input entries doesn't match the number of inputs for decision table {decisionName}. Rule Id:{sourceRule.Id} ");
                }

                if (sourceRule.OutputEntries == null || sourceRule.OutputEntries.Count != outputs.Count)
                {
                    throw Logger.Fatal <DmnParserException>($"Number of output entries doesn't match the number of outputs for decision table {decisionName}. Rule Id:{sourceRule.Id} ");
                }

                var ruleInputs  = new List <DmnDecisionTableRuleInput>();
                var ruleOutputs = new List <DmnDecisionTableRuleOutput>();
                var ruleName    = string.IsNullOrWhiteSpace(sourceRule.Label) ? sourceRule.Id : sourceRule.Label;

                //inputs
                var ruleInputIdx = 0;
                foreach (var sourceRuleInputEntry in sourceRule.InputEntries)
                {
                    if (!string.IsNullOrWhiteSpace(sourceRuleInputEntry.Text) && sourceRuleInputEntry.Text != "-") //don't create rule inputs with no condition - can be also represented as single dash
                    {
                        var ruleInput = new DmnDecisionTableRuleInput(inputs[ruleInputIdx], sourceRuleInputEntry.Text);
                        ruleInputs.Add(ruleInput);
                    }
                    ruleInputIdx++;
                }

                //outputs
                var ruleOutputIdx = 0;
                foreach (var sourceRuleOutputEntry in sourceRule.OutputEntries)
                {
                    var ruleOutput = new DmnDecisionTableRuleOutput(outputs[ruleOutputIdx], sourceRuleOutputEntry.Text);
                    ruleOutputs.Add(ruleOutput);
                    ruleOutputIdx++;
                }

                rules.Add(new DmnDecisionTableRule(ruleIdx, ruleName, ruleInputs.ToArray(), ruleOutputs.ToArray(), sourceRule.Description));
                ruleIdx++;
            }

            var decisionTable = new DmnDecisionTable(
                decisionName,
                sourceTable.HitPolicy, sourceTable.Aggregation,
                inputs.ToArray(), outputs.ToArray(), rules.ToArray(),
                requiredInputs, requiredDecisions);

            return(decisionTable);
        }