Esempio n. 1
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void testEvaluateDecisionByKeyAndTenantId()
        public virtual void testEvaluateDecisionByKeyAndTenantId()
        {
            DecisionDefinition mockDefinition = MockProvider.mockDecisionDefinition().tenantId(MockProvider.EXAMPLE_TENANT_ID).build();

            UpRuntimeData = mockDefinition;

            DmnDecisionResult decisionResult = MockProvider.createMockDecisionResult();

            when(decisionEvaluationBuilderMock.evaluate()).thenReturn(decisionResult);

            IDictionary <string, object> json = new Dictionary <string, object>();

            json["variables"] = VariablesBuilder.create().variable("amount", 420).variable("invoiceCategory", "MISC").Variables;

            given().pathParam("key", MockProvider.EXAMPLE_DECISION_DEFINITION_KEY).pathParam("tenant-id", MockProvider.EXAMPLE_TENANT_ID).contentType(POST_JSON_CONTENT_TYPE).body(json).then().expect().statusCode(Status.OK.StatusCode).when().post(EVALUATE_DECISION_BY_KEY_AND_TENANT_ID_URL);

            IDictionary <string, object> expectedVariables = new Dictionary <string, object>();

            expectedVariables["amount"]          = 420;
            expectedVariables["invoiceCategory"] = "MISC";

            verify(decisionDefinitionQueryMock).tenantIdIn(MockProvider.EXAMPLE_TENANT_ID);
            verify(decisionEvaluationBuilderMock).variables(expectedVariables);
            verify(decisionEvaluationBuilderMock).evaluate();
        }
Esempio n. 2
0
 /// <summary>
 /// Creates the execution context snapshot - to be called by decision after the evaluation
 /// </summary>
 /// <param name="decision">Decision evaluated just before the snapshot</param>
 /// <param name="result"><paramref name="decision"/> result</param>
 internal virtual void CreateSnapshot(IDmnDecision decision, DmnDecisionResult result)
 {
     if (Options.RecordSnapshots)
     {
         Snapshots.CreateSnapshot(this, decision, result);
     }
 }
Esempio n. 3
0
        [DataRow(9, 9, null, 0)]       //no hit
        public void UniqueHitPolicyTest(int?a, int?b, string hit, int hitsCount)
        {
            var def = new DmnDefinitionBuilder()
                      .WithInput <int>("a", out var aRef)
                      .WithInput <int>("b", out var bRef)
                      .WithVariable <string>("o", out var oRef)

                      .WithTableDecision("Unique", table =>
                                         table
                                         .WithInput(aRef, out var inputARef)
                                         .WithInput(bRef, out var inputBRef)
                                         .WithOutput(oRef, out var outputRef)
                                         .WithHitPolicy(HitPolicyEnum.Unique)
                                         .WithRule("r1", r => r
                                                   .When(inputARef, "< 5").And(inputBRef, "1").Then(outputRef, "\"r1\""))
                                         .WithRule("r2", "err not unique for 5 - 2", r => r
                                                   .When(inputARef, "<= 5").And(inputBRef, "2").Then(outputRef, "\"r2\""))
                                         .WithRule("r3", r => r
                                                   .When(inputARef, "5").And(inputBRef, "1").Then(outputRef, "\"r3\""))
                                         .WithRule("r4", "err not unique for 5 - 2", r => r
                                                   .When(inputARef, "5").And(inputBRef, "2").Then(outputRef, "\"r4\""))
                                         .WithRule("r5", "err not unique for 6-3", r => r
                                                   .When(inputARef, "6").Then(outputRef, "\"r5\""))
                                         .WithRule("r6", r => r
                                                   .When(inputARef, "> 6").And(inputBRef, "2").Then(outputRef, "\"r6\""))
                                         .WithRule("rEmpty", "empty out", r => r
                                                   .When(inputARef, "> 6").And(inputBRef, "1").Then(outputRef, ""))
                                         .WithRule("r8", "err not unique for 6-3", r => r
                                                   .When(inputBRef, "3").Then(outputRef, "\"r8\""))
                                         .Requires(aRef).Requires(bRef))
                      .Build();

            var ctx = DmnExecutionContextFactory
                      .CreateExecutionContext(def)
                      .WithInputParameter("a", a)
                      .WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Unique"); };

            if (hitsCount < 0)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("UNIQUE hit policy violation*");
                return;
            }

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();
            result.Results.Should().HaveCount(hitsCount);

            if (hitsCount == 0)
            {
                return;
            }
            result.Results[0].HitRules.Should().HaveCount(1);
            result.Results[0].HitRules[0].Name.Should().Be(hit ?? "rEmpty");
        }
Esempio n. 4
0
        protected internal virtual ISet <string> collectOutputNames(DmnDecisionResult decisionResult)
        {
            ISet <string> outputNames = new HashSet <string>();

            foreach (IDictionary <string, object> entryMap in decisionResult.ResultList)
            {
                outputNames.addAll(entryMap.Keys);
            }

            return(outputNames);
        }
Esempio n. 5
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void testEvaluateDecisionMultipleDecisionValues()
        public virtual void testEvaluateDecisionMultipleDecisionValues()
        {
            DmnDecisionResult decisionResult = (new MockDecisionResultBuilder()).resultEntries().entry("status", Variables.stringValue("gold")).entry("assignee", Variables.stringValue("manager")).build();

            when(decisionEvaluationBuilderMock.evaluate()).thenReturn(decisionResult);

            IDictionary <string, object> json = new Dictionary <string, object>();

            json["variables"] = Collections.emptyMap();

            given().pathParam("id", MockProvider.EXAMPLE_DECISION_DEFINITION_ID).contentType(POST_JSON_CONTENT_TYPE).body(json).then().expect().statusCode(Status.OK.StatusCode).body("size()", @is(1)).body("[0].size()", @is(2)).body("[0].status.value", @is("gold")).body("[0].assignee.value", @is("manager")).when().post(EVALUATE_DECISION_URL);
        }
        [DataRow(9, 9, null, 0, 0)]       //no hit
        public void UniqueHitPolicyTest(int?a, int?b, string c, int hitsCount, int outVariableCount)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_Unique.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Unique"); };

            if (hitsCount < 0)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("UNIQUE hit policy violation*");
                return;
            }

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.SingleResult.Should().NotBeNull();
                result.SingleResult.Should().HaveCount(outVariableCount);
            }

            if (outVariableCount <= 0)
            {
                return;
            }

            var output = result.SingleResult[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("o");
            output.Value.Should().Be(c).And.BeOfType <string>();
            output.Type.Should().Be(typeof(string));
        }
Esempio n. 7
0
        [DataRow(9, 9, null, 0, 0)]       //no hit
        public void UniqueHitPolicyTest(int?a, int?b, string c, int hitsCount, int outVariableCount)
        {
            var ctx = CTX("hitpolicy_Unique.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Unique"); };

            if (hitsCount < 0)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("UNIQUE hit policy violation*");
                return;
            }

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.FirstResultVariables.Should().NotBeNull();
                result.FirstResultVariables.Should().HaveCount(outVariableCount);
                result.Results[0].HitRules.Should().HaveCount(1);
            }

            if (outVariableCount <= 0)
            {
                return;
            }

            var output = result.FirstResultVariables[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("o");
            output.Value.Should().Be(c).And.BeOfType <string>();
            output.Type.Should().Be(typeof(string));
        }
        [DataRow(8, 8, null, 0, new[] { 0 })]       //no hit
        public void OutputOrderHitPolicyTest(int?a, int?b, string[] c, int hitsCount, int[] outVariableCount)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_OutputOrder.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("OutputOrder"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.SingleResult.Should().NotBeNull();
                result.SingleResult.Should().HaveCount(outVariableCount[0]);
            }

            for (var i = 0; i < hitsCount; i++)
            {
                if (outVariableCount[i] <= 0)
                {
                    result.Results[i].Variables.Should().HaveCount(0);
                    continue;
                }

                result.Results[i].Variables.Should().HaveCount(1);
                var output = result.Results[i].Variables[0];
                output.Should().NotBeNull();
                output.Name.Should().Be("o");
                output.Value.Should().Be(c[i]).And.BeOfType <string>();
                output.Type.Should().Be(typeof(string));
            }
        }
Esempio n. 9
0
        [DataRow(8, 8, null, 0, new[] { 0 })]       //no hit
        public void OutputOrderHitPolicyTest(int?a, int?b, string[] c, int hitsCount, int[] outVariableCount)
        {
            var ctx = CTX("hitpolicy_OutputOrder.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("OutputOrder"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.FirstResultVariables.Should().NotBeNull();
                result.FirstResultVariables.Should().HaveCount(outVariableCount[0]);
            }

            for (var i = 0; i < hitsCount; i++)
            {
                if (outVariableCount[i] <= 0)
                {
                    result.Results[i].Variables.Should().HaveCount(0);
                    continue;
                }

                result.Results[i].Variables.Should().HaveCount(1);
                result.Results[i].HitRules.Should().HaveCount(1);
                var output = result.Results[i].Variables[0];
                output.Should().NotBeNull();
                output.Name.Should().Be("o");
                output.Value.Should().Be(c[i]).And.BeOfType <string>();
                output.Type.Should().Be(typeof(string));
            }
        }
        [DataRow(8, 8, false, 0)]       //no hit
        public void CollectMaxBoolHitPolicyTest(int?a, int?b, bool?c, int hitsCount)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_Collect_MaxBool.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Collect"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);

            result.IsSingleResult.Should().Be(true);
            result.SingleResult.Should().NotBeNull();
            result.SingleResult.Should().HaveCount(1);

            result.Results[0].Variables.Should().HaveCount(1);
            var output = result.Results[0].Variables[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("o");
            if (c != null)
            {
                output.Value.Should().Be(c).And.BeOfType <bool>();
                output.Type.Should().Be(typeof(bool));
            }
            else
            {
                output.Value.Should().BeNull();
                output.Type.Should().Be(typeof(bool));
            }
        }
Esempio n. 11
0
        [DataRow(8, 8, 0, 0)]       //no hit
        public void CollectCountStrHitPolicyTest(int?a, int?b, int?c, int hitsCount)
        {
            var ctx = CTX("hitpolicy_Collect_CountStr.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Collect"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(1);
            result.HasResult.Should().Be(true);

            result.IsSingleResult.Should().Be(true);
            result.FirstResultVariables.Should().NotBeNull();
            result.FirstResultVariables.Should().HaveCount(1);

            result.Results[0].Variables.Should().HaveCount(1);
            result.Results[0].HitRules.Should().HaveCount(hitsCount);
            var output = result.Results[0].Variables[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("o");
            if (c != null)
            {
                output.Value.Should().Be(c.ToString()).And.BeOfType <string>();
                output.Type.Should().Be(typeof(string));
            }
            else
            {
                output.Value.Should().BeNull();
                output.Type.Should().Be(typeof(string));
            }
        }
Esempio n. 12
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void testEvaluateDecisionById()
        public virtual void testEvaluateDecisionById()
        {
            DmnDecisionResult decisionResult = MockProvider.createMockDecisionResult();

            when(decisionEvaluationBuilderMock.evaluate()).thenReturn(decisionResult);

            IDictionary <string, object> json = new Dictionary <string, object>();

            json["variables"] = VariablesBuilder.create().variable("amount", 420).variable("invoiceCategory", "MISC").Variables;

            given().pathParam("id", MockProvider.EXAMPLE_DECISION_DEFINITION_ID).contentType(POST_JSON_CONTENT_TYPE).body(json).then().expect().statusCode(Status.OK.StatusCode).when().post(EVALUATE_DECISION_URL);

            IDictionary <string, object> expectedVariables = new Dictionary <string, object>();

            expectedVariables["amount"]          = 420;
            expectedVariables["invoiceCategory"] = "MISC";

            verify(decisionEvaluationBuilderMock).variables(expectedVariables);
            verify(decisionEvaluationBuilderMock).evaluate();
        }
Esempio n. 13
0
 public virtual object mapDecisionResult(DmnDecisionResult decisionResult)
 {
     if (decisionResult.Empty)
     {
         return(Collections.emptyList());
     }
     else
     {
         ISet <string> outputNames = collectOutputNames(decisionResult);
         if (outputNames.Count > 1)
         {
             throw LOG.decisionResultCollectMappingException(outputNames, decisionResult, this);
         }
         else
         {
             string outputName = outputNames.GetEnumerator().next();
             return(decisionResult.collectEntries(outputName));
         }
     }
 }
        public void AllowedValuesTest(string a, string b, string c, bool validIn, bool validOut)
        {
            var ctx = CTX("allowedValues.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Test"); };

            if (!validIn && validOut)
            {
                act.Should().NotThrow();
                result.HasResult.Should().BeFalse();
                //act.Should().Throw<DmnExecutorException>().WithMessage("Decision table Test, *Input value * is not in allowed values list *");
                return;
            }

            if (!validOut)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("Decision table Test,* Output value * is not in allowed values list *");
                return;
            }

            act.Invoke();

            result.Should().NotBeNull();
            result.IsSingleResult.Should().Be(true);
            result.FirstResultVariables.Should().NotBeNull();
            result.FirstResultVariables.Should().HaveCount(1);
            result.Results[0].HitRules.Should().HaveCount(1);

            var output = result.FirstResultVariables[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("c");
            output.Value.Should().Be(c).And.BeOfType <string>();
            output.Type.Should().Be(typeof(string));
        }
        public void AllowedValuesTest(string a, string b, string c, bool validIn, bool validOut)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/allowedValues.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse(file, DmnParser.DmnVersionEnum.V1_3));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Test"); };

            if (!validIn && validOut)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("Decision table Test,* Input value * is not in allowed values list *");
                return;
            }

            if (!validOut)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("Decision table Test,* Output value * is not in allowed values list *");
                return;
            }

            act.Invoke();

            result.Should().NotBeNull();
            result.IsSingleResult.Should().Be(true);
            result.SingleResult.Should().NotBeNull();
            result.SingleResult.Should().HaveCount(1);

            var output = result.SingleResult[0];

            output.Should().NotBeNull();
            output.Name.Should().Be("c");
            output.Value.Should().Be(c).And.BeOfType <string>();
            output.Type.Should().Be(typeof(string));
        }
Esempio n. 16
0
        public virtual IList <IDictionary <string, VariableValueDto> > evaluateDecision(UriInfo context, EvaluateDecisionDto parameters)
        {
            DecisionService decisionService = engine.DecisionService;

            IDictionary <string, object> variables = VariableValueDto.toMap(parameters.Variables, engine, objectMapper);

            try
            {
                DmnDecisionResult decisionResult = decisionService.evaluateDecisionById(decisionDefinitionId).variables(variables).evaluate();

                return(createDecisionResultDto(decisionResult));
            }
            catch (AuthorizationException e)
            {
                throw e;
            }
            catch (NotFoundException e)
            {
                string errorMessage = string.Format("Cannot evaluate decision {0}: {1}", decisionDefinitionId, e.Message);
                throw new InvalidRequestException(Response.Status.NOT_FOUND, e, errorMessage);
            }
            catch (NotValidException e)
            {
                string errorMessage = string.Format("Cannot evaluate decision {0}: {1}", decisionDefinitionId, e.Message);
                throw new InvalidRequestException(Response.Status.BAD_REQUEST, e, errorMessage);
            }
            catch (ProcessEngineException e)
            {
                string errorMessage = string.Format("Cannot evaluate decision {0}: {1}", decisionDefinitionId, e.Message);
                throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e, errorMessage);
            }
            catch (DmnEngineException e)
            {
                string errorMessage = string.Format("Cannot evaluate decision {0}: {1}", decisionDefinitionId, e.Message);
                throw new RestException(Response.Status.INTERNAL_SERVER_ERROR, e, errorMessage);
            }
        }
Esempio n. 17
0
        [DataRow(8, 8, new int[] { }, 0, new[] { 0 })]       //no hit
        public void CollectListHitPolicyTest(int?a, int?b, int[] cIn, int hitsCount, int[] outVariableCount)
        {
            var c = new int?[cIn.Length];

            for (var i = 0; i < cIn.Length; i++)
            {
                if (cIn[i] >= 0)
                {
                    c[i] = cIn[i];
                }
                else
                {
                    c[i] = null;
                }
            }
            var ctx = CTX("hitpolicy_Collect_List.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Collect"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.FirstResultVariables.Should().NotBeNull();
                result.FirstResultVariables.Should().HaveCount(outVariableCount[0]);
            }

            for (var i = 0; i < hitsCount; i++)
            {
                if (outVariableCount[i] <= 0)
                {
                    result.Results[i].Variables.Should().HaveCount(0);
                    continue;
                }

                result.Results[i].Variables.Should().HaveCount(1);
                result.Results[i].HitRules.Should().HaveCount(1);
                var output = result.Results[i].Variables[0];
                output.Should().NotBeNull();
                output.Name.Should().Be("o");
                output.Value.Should().Be(c[i]).And.BeOfType <long>();
                output.Type.Should().Be(typeof(long));
            }
        }
Esempio n. 18
0
 public virtual ProcessEngineException decisionResultMappingException(DmnDecisionResult decisionResult, DecisionResultMapper resultMapper, DmnEngineException cause)
 {
     return(new ProcessEngineException(exceptionMessage("001", "The decision result mapper '{}' failed to process '{}'", resultMapper, decisionResult), cause));
 }
 /// <summary>
 /// CTOR
 /// </summary>
 /// <param name="step">Sequence number of the execution step</param>
 /// <param name="ctx">Execution context to create snapshot for</param>
 /// <param name="decision">Decision executed just before snapshot</param>
 /// <param name="result">Result of the decision executed just before snapshot</param>
 internal DmnExecutionSnapshot(int step, DmnExecutionContext ctx, IDmnDecision decision, DmnDecisionResult result)
     : this(step, ctx)
 {
     Decision       = decision;
     DecisionResult = result?.Clone();
 }
        [DataRow(null, null, new[] { "" }, new[] { -1 }, new[] { "" }, false)]            //null -> 0
        public void RuleOrderHitPolicyMultiOutTest(int?a, int?b, string[] o1, int[] o2, string[] o3, bool hasHit)
        {
            var ctx = CTX("hitpolicy_MultiOut_RuleOrder.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("RuleOrder"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (!hasHit)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            var hitsCount = o1.Length;

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);

            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.FirstResultVariables.Should().NotBeNull();
            }

            result.Results.Should().HaveCount(hitsCount);
            var idx = 0;

            foreach (var resultHit in result.Results)
            {
                resultHit.HitRules.Should().HaveCount(1);
                var o1Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o1");
                var o2Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o2");
                var o3Result = resultHit.Variables?.FirstOrDefault(v => v.Name == "o3");
                var o1Assert = o1[idx];
                var o2Assert = o2[idx];
                var o3Assert = o3[idx];

                if (o1Result == null)
                {
                    o1Assert.Should().BeNull();
                }
                else
                {
                    o1Result.Should().NotBeNull();
                    o1Result.Value.Should().NotBeNull();
                    o1Result.Value.Should().Be(o1Assert).And.BeOfType <string>();
                    o1Result.Type.Should().Be(typeof(string));
                }
                if (o2Result == null)
                {
                    o2Assert.Should().Be(-1); //-1 means null
                }
                else
                {
                    o2Result.Should().NotBeNull();
                    o2Result.Value.Should().NotBeNull();
                    o2Result.Value.Should().Be(o2Assert).And.BeOfType <int>();
                    o2Result.Type.Should().Be(typeof(int));
                }
                if (o3Result == null)
                {
                    o3Assert.Should().BeNull();
                }
                else
                {
                    o3Result.Should().NotBeNull();
                    o3Result.Value.Should().NotBeNull();
                    o3Result.Value.Should().Be(o3Assert).And.BeOfType <string>();
                    o3Result.Type.Should().Be(typeof(string));
                }
                idx++;
            }
        }
        /// <summary>
        /// Evaluates the decision table.
        /// </summary>
        /// <remarks>
        /// While evaluating the decision table, the <seealso cref="Rules"/> are evaluated first.
        /// Then it evaluates (calculates) the outputs for positive rules and applies the hit policy.
        /// </remarks>
        /// <param name="context">DMN Engine execution context</param>
        /// <param name="correlationId">Optional correlation ID used while logging</param>
        /// <returns>Decision result</returns>
        /// <exception cref="ArgumentNullException"><paramref name="context"/> is null</exception>
        protected override DmnDecisionResult Evaluate(DmnExecutionContext context, string correlationId = null)
        {
            if (context == null)
            {
                throw Logger.FatalCorr <ArgumentNullException>(correlationId, $"{nameof(context)} is null");
            }

            //EVALUATE RULES
            var positiveRules = EvaluateRules(context, correlationId);

            //EVALUATE OUTPUTS for positive rules
            var results = EvaluateOutputsForPositiveRules(context, correlationId, positiveRules);

            //APPLY HIT POLICY
            if (positiveRules.Count <= 0)
            {
                return(new DmnDecisionResult());
            }

            var retVal = new DmnDecisionResult();
            var positiveMatchOutputRules = new List <DmnDecisionTableRule>();

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (HitPolicy)
            {
            case HitPolicyEnum.Unique:
                // No overlap is possible and all rules are disjoint. Only a single rule can be matched
                // Overlapping rules represent an error.
                if (positiveRules.Count > 1)
                {
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"UNIQUE hit policy violation - {positiveRules.Count} matches");
                }
                positiveMatchOutputRules.Add(positiveRules[0]);
                break;

            case HitPolicyEnum.First:
                //Multiple(overlapping) rules can match, with different output entries. The first hit by rule order is returned
                positiveMatchOutputRules.Add(positiveRules[0]);
                break;

            case HitPolicyEnum.Priority:
                // Multiple rules can match, with different output entries. This policy returns the matching rule with the highest output priority.
                //  Output priorities are specified in the ordered list of output values, in decreasing order of priority. Note that priorities are independent from rule sequence
                // A P table that omits allowed output values is an error.
                var orderedPositiveRules = OrderPositiveRulesByOutputPriority(positiveRules, results, correlationId);
                if (orderedPositiveRules == null)
                {
                    //A P table that omits allowed output values is an error.
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"PRIORITY hit policy violation - no outputs with Allowed Values");
                }
                positiveMatchOutputRules.Add(orderedPositiveRules.ToArray()[0]);
                break;

            case HitPolicyEnum.Any:
                //  There may be overlap, but all of the matching rules show equal output entries for each output, so any match can be used.
                //  If the output entries are non-equal, the hit policy is incorrect and the result is an error.
                if (!MatchRuleOutputs(positiveRules, results))
                {
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"ANY hit policy violation - the outputs don't match");
                }
                positiveMatchOutputRules.Add(positiveRules[0]);
                break;


            case HitPolicyEnum.Collect:
                // Multiple rules can be satisfied. The decision table result contains the output of all satisfied rules in an arbitrary order as a list.
                // If an aggregator is specified, the decision table result will only contain a single output entry. The aggregator will generate the output entry from all satisfied rules.
                // Except for C-count and C-list, the rules must have numeric output values (bool is also allowed - 0=false, 1=true).
                // If the Collect hit policy is used with an aggregator, the decision table can only have one output.
                if (Outputs.Count > 1 && Aggregation != CollectHitPolicyAggregationEnum.List)
                {
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"COLLECT hit policy violation - multiple outputs not allowed for aggregation {Aggregation}");
                }

                var outType          = Outputs[0].Variable.Type;
                var outTypeIsNumeric = outType == typeof(int) || outType == typeof(long) || outType == typeof(double);
                var outTypeIsBool    = outType == typeof(bool);
                var outTypeIsStr     = outType == typeof(string);

                var isAllowedForCount     = outTypeIsNumeric || outTypeIsStr;
                var isAllowedForSumMinMax = outTypeIsNumeric || outTypeIsBool;

                if (!
                    (Aggregation == CollectHitPolicyAggregationEnum.List ||
                     (Aggregation == CollectHitPolicyAggregationEnum.Count && isAllowedForCount) ||
                     Aggregation != CollectHitPolicyAggregationEnum.List && Aggregation != CollectHitPolicyAggregationEnum.Count && isAllowedForSumMinMax))
                {
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"COLLECT hit policy violation - type {outType.Name} not allowed for aggregation {Aggregation}");
                }


                if (Aggregation == CollectHitPolicyAggregationEnum.List)
                {
                    positiveMatchOutputRules.AddRange(positiveRules);
                }
                else
                {
                    var collectValues = isAllowedForSumMinMax ?
                                        CalculatePositiveRulesCollectValues(positiveRules, results) :
                                        CalculatePositiveRulesCollectCountValue(positiveRules, results);

                    var output         = Outputs[0];
                    var outputVariable = context.GetVariable(output.Variable);
                    if (collectValues.Count == 0 && Aggregation != CollectHitPolicyAggregationEnum.Count)
                    {
                        //no value for sum, min, max
                        outputVariable.Value = null;
                        retVal += new DmnDecisionSingleResult() + outputVariable.Clone();
                        return(retVal);
                    }
                    // ReSharper disable once SwitchStatementMissingSomeCases
                    switch (Aggregation)
                    {
                    case CollectHitPolicyAggregationEnum.Sum:
                        outputVariable.Value = collectValues.Sum;
                        break;

                    case CollectHitPolicyAggregationEnum.Min:
                        outputVariable.Value = collectValues.Min;
                        break;

                    case CollectHitPolicyAggregationEnum.Max:
                        outputVariable.Value = collectValues.Max;
                        break;

                    case CollectHitPolicyAggregationEnum.Count:
                        outputVariable.Value = collectValues.Count;
                        break;
                    }

                    retVal += new DmnDecisionSingleResult() + outputVariable.Clone();
                    return(retVal);
                }

                break;

            case HitPolicyEnum.RuleOrder:
                //Multiple rules can be satisfied.The decision table result contains the output of all satisfied rules in the order of the rules in the decision table.
                positiveMatchOutputRules.AddRange(positiveRules);

                break;

            case HitPolicyEnum.OutputOrder:
                //Returns all hits in decreasing output priority order.
                // Output priorities are specified in the ordered list of output values in decreasing order of priority
                var orderedPositiveRules2 = OrderPositiveRulesByOutputPriority(positiveRules, results, correlationId);
                if (orderedPositiveRules2 == null)
                {
                    //A P table that omits allowed output values is an error.
                    throw Logger.ErrorCorr <DmnExecutorException>(
                              correlationId,
                              $"OUTPUT ORDER hit policy violation - no outputs with Allowed Values");
                }
                positiveMatchOutputRules.AddRange(orderedPositiveRules2);
                break;
            }

            //Return (multiple) matches
            foreach (var multiMatchOutputRule in positiveMatchOutputRules)
            {
                var singleResult = new DmnDecisionSingleResult();
                foreach (var ruleOutput in multiMatchOutputRule.Outputs)
                {
                    var resultOutput = results.GetResult(multiMatchOutputRule, ruleOutput);
                    if (resultOutput == null)
                    {
                        continue;
                    }

                    context.GetVariable(ruleOutput.Output.Variable).Value = resultOutput.Value;
                    singleResult += resultOutput;
                }

                retVal += singleResult;
            }

            return(retVal);
        }
Esempio n. 22
0
 /// <summary>
 /// Creates the snapshot with the decision information
 /// </summary>
 /// <param name="ctx">Execution context to create snapshot for</param>
 /// <param name="decision">Decision executed just before snapshot</param>
 /// <param name="result">Result of the decision executed just before snapshot</param>
 internal void CreateSnapshot(DmnExecutionContext ctx, IDmnDecision decision, DmnDecisionResult result)
 {
     snapshots.Add(new DmnExecutionSnapshot(snapshots.Count, ctx, decision, result));
 }
Esempio n. 23
0
        [DataRow(8, 8, new int[] { }, 0, new[] { 0 })]       //no hit
        public void CollectListHitPolicyTest(int?a, int?b, int[] cIn, int hitsCount, int[] outVariableCount)
        {
            var c = new int?[cIn.Length];

            for (var i = 0; i < cIn.Length; i++)
            {
                if (cIn[i] >= 0)
                {
                    c[i] = cIn[i];
                }
                else
                {
                    c[i] = null;
                }
            }
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/hitpolicy_Collect_List.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Collect"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (hitsCount <= 0)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);
            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.SingleResult.Should().NotBeNull();
                result.SingleResult.Should().HaveCount(outVariableCount[0]);
            }

            for (var i = 0; i < hitsCount; i++)
            {
                if (outVariableCount[i] <= 0)
                {
                    result.Results[i].Variables.Should().HaveCount(0);
                    continue;
                }

                result.Results[i].Variables.Should().HaveCount(1);
                var output = result.Results[i].Variables[0];
                output.Should().NotBeNull();
                output.Name.Should().Be("o");
                output.Value.Should().Be(c[i]).And.BeOfType <long>();
                output.Type.Should().Be(typeof(long));
            }
        }
Esempio n. 24
0
        protected internal virtual IList <IDictionary <string, VariableValueDto> > createDecisionResultDto(DmnDecisionResult decisionResult)
        {
            IList <IDictionary <string, VariableValueDto> > dto = new List <IDictionary <string, VariableValueDto> >();

            foreach (DmnDecisionResultEntries entries in decisionResult)
            {
                IDictionary <string, VariableValueDto> resultEntriesDto = createResultEntriesDto(entries);
                dto.Add(resultEntriesDto);
            }

            return(dto);
        }
Esempio n. 25
0
        public void AnyHitPolicyMultiOutTest(int?a, int?b, string o1, int?o2, bool hasHit, bool isErr)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_MultiOut_Any.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Any"); };

            if (isErr)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("ANY hit policy violation - the outputs don't match");
                return;
            }
            act.Invoke();


            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (!hasHit)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(1);
            result.HasResult.Should().Be(true);

            result.IsSingleResult.Should().Be(true);
            result.SingleResult.Should().NotBeNull();
            var outCount = 2;
            var o1Index  = 0;
            var o2Index  = 1;

            if (o1 == null)
            {
                outCount--;
                o1Index = -1;
                o2Index--;
            }
            if (o2 == null)
            {
                outCount--;
                o2Index = -1;
            }

            result.SingleResult.Should().HaveCount(outCount);

            if (o1Index >= 0)
            {
                var output1 = result.SingleResult[o1Index];
                output1.Should().NotBeNull();
                output1.Name.Should().Be("o1");
                output1.Value.Should().Be(o1).And.BeOfType <string>();
                output1.Type.Should().Be(typeof(string));
            }

            // ReSharper disable once InvertIf
            if (o2Index >= 0)
            {
                var output2 = result.SingleResult[o2Index];
                output2.Should().NotBeNull();
                output2.Name.Should().Be("o2");
                output2.Value.Should().Be(o2).And.BeOfType <int>();
                output2.Type.Should().Be(typeof(int));
            }
        }
        public void AnyHitPolicyMultiOutTest(int?a, int?b, string o1, int?o2, bool hasHit, bool isErr)
        {
            var ctx = CTX("hitpolicy_MultiOut_Any.dmn");

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("Any"); };

            if (isErr)
            {
                act.Should().Throw <DmnExecutorException>().WithMessage("ANY hit policy violation - the outputs don't match");
                return;
            }
            act.Invoke();


            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (!hasHit)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            result.Results.Should().HaveCount(1);
            result.HasResult.Should().Be(true);
            result.Results[0].HitRules.Should().HaveCount(1);

            result.IsSingleResult.Should().Be(true);
            result.FirstResultVariables.Should().NotBeNull();
            var outCount = 2;
            var o1Index  = 0;
            var o2Index  = 1;

            if (o1 == null)
            {
                outCount--;
                o1Index = -1;
                o2Index--;
            }
            if (o2 == null)
            {
                outCount--;
                o2Index = -1;
            }

            result.FirstResultVariables.Should().HaveCount(outCount);

            if (o1Index >= 0)
            {
                var output1 = result.FirstResultVariables[o1Index];
                output1.Should().NotBeNull();
                output1.Name.Should().Be("o1");
                output1.Value.Should().Be(o1).And.BeOfType <string>();
                output1.Type.Should().Be(typeof(string));
            }

            // ReSharper disable once InvertIf
            if (o2Index >= 0)
            {
                var output2 = result.FirstResultVariables[o2Index];
                output2.Should().NotBeNull();
                output2.Name.Should().Be("o2");
                output2.Value.Should().Be(o2).And.BeOfType <int>();
                output2.Type.Should().Be(typeof(int));
            }
        }
Esempio n. 27
0
        [DataRow(null, null, new[] { "" }, new[] { -1 }, new[] { "" }, false)]            //null -> 0
        public void RuleOrderHitPolicyMultiOutTest(int?a, int?b, string[] o1, int[] o2, string[] o3, bool hasHit)
        {
            var dir  = AppDomain.CurrentDomain.BaseDirectory;
            var file = Path.Combine(dir, "dmn/dmn1.3/hitpolicy_MultiOut_RuleOrder.dmn");
            var ctx  = DmnExecutionContextFactory.CreateExecutionContext(DmnParser.Parse13(file));

            ctx.WithInputParameter("a", a);
            ctx.WithInputParameter("b", b);

            DmnDecisionResult result = null;
            Action            act    = () => { result = ctx.ExecuteDecision("RuleOrder"); };

            act.Invoke();

            result.Should().NotBeNull();
            result.Results.Should().NotBeNull();

            if (!hasHit)
            {
                result.Results.Should().HaveCount(0);
                result.HasResult.Should().Be(false);
                result.IsSingleResult.Should().Be(false);
                return;
            }

            var hitsCount = o1.Length;

            result.Results.Should().HaveCount(hitsCount);
            result.HasResult.Should().Be(true);

            if (hitsCount == 1)
            {
                result.IsSingleResult.Should().Be(true);
                result.SingleResult.Should().NotBeNull();
            }

            result.Results.Should().HaveCount(hitsCount);
            var idx = 0;

            foreach (var resultHit in result.Results)
            {
                var o1Result  = resultHit.Variables?.FirstOrDefault(v => v.Name == "o1");
                var o2Result  = resultHit.Variables?.FirstOrDefault(v => v.Name == "o2");
                var o3Result  = resultHit.Variables?.FirstOrDefault(v => v.Name == "o3");
                var o1Asserrt = o1[idx];
                var o2Asserrt = o2[idx];
                var o3Asserrt = o3[idx];

                if (o1Result == null)
                {
                    o1Asserrt.Should().BeNull();
                }
                else
                {
                    o1Result.Should().NotBeNull();
                    o1Result.Value.Should().NotBeNull();
                    o1Result.Value.Should().Be(o1Asserrt).And.BeOfType <string>();
                    o1Result.Type.Should().Be(typeof(string));
                }
                if (o2Result == null)
                {
                    o2Asserrt.Should().Be(-1); //-1 means null
                }
                else
                {
                    o2Result.Should().NotBeNull();
                    o2Result.Value.Should().NotBeNull();
                    o2Result.Value.Should().Be(o2Asserrt).And.BeOfType <int>();
                    o2Result.Type.Should().Be(typeof(int));
                }
                if (o3Result == null)
                {
                    o3Asserrt.Should().BeNull();
                }
                else
                {
                    o3Result.Should().NotBeNull();
                    o3Result.Value.Should().NotBeNull();
                    o3Result.Value.Should().Be(o3Asserrt).And.BeOfType <string>();
                    o3Result.Type.Should().Be(typeof(string));
                }
                idx++;
            }
        }
Esempio n. 28
0
 public virtual ProcessEngineException decisionResultCollectMappingException(ICollection <string> outputNames, DmnDecisionResult decisionResult, DecisionResultMapper resultMapper)
 {
     return(new ProcessEngineException(exceptionMessage("002", "The decision result mapper '{}' failed to process '{}'. The decision outputs should only contains values for one output name but found '{}'.", resultMapper, decisionResult, outputNames)));
 }