DecisionToolkit / dsntk-rs

Decision Toolkit written in Rust
Apache License 2.0
14 stars 0 forks source link

How to check in a decision table for and empty string? #26

Closed antback closed 6 months ago

antback commented 7 months ago

Hi,

Sorry to bother :-)

I'm trying to check if a value is empty in a decision table. Like this:

image

Providing the following data:

{
    "legalName": ""
}

The result is "pass", so the condition of the second rule is not working. I have been trying other alternatives like matches(legalName, "[a-zA-Z]+") but nothing seems to work.

Any Idea how to achieve it?

Thanks!!

dsntk commented 7 months ago

Hi @antback, let's find out what is going on here ;-)

This decision table will not work (in DSNTK) for two reasons:

  1. The input entries in the fist input clause contain values of different types. In the first rule, the value of the input variable legalName is compared with string "Google" and it is ok. The result of this comparison may be true or false, and this rule will match or not accordingly. In the second rule, the value of the input variable legalName of type string is compared with value of type boolean (function matches returns true or false). In such case the result of this comparison is always Null, so this rule will never match.
  2. I may look like the rule 2 matches and the result is "pass" for an empty string, but the reason is in hit policy. In this decision table the P hit policy is specified, but no ordered list of output values are defined for Status output clause.

So, one possible fix to this decision table could look like this:

image

Below is another example of a decision table that checks directly against an empty string, but the input value legalName may contain other characters then specified in match function in the above example.

image

Yet another approach. Maybe this one is the closest to the goal you wanted to achieve:

image

And if we would like to be really strict, then maybe this decision table would be more appropriate:

image

If you would have any further questions, please do not hesitate to reach out. Thanks for trying DSNTK!

PS: In the next comment I will put all the sources I used to test your case, so you can try it too.

dsntk commented 7 months ago

Inputs used in all test examples:

in_digits.ctx: legalName contains digits.

$ cat in_digits.ctx
{ "legalName": " Company 1 " }

in_empty.ctx: legalName is an empty string.

$ cat in_empty.ctx
{ "legalName": "" }

in_google.ctx: legalName is "Google".

$ cat in_google.ctx
{ "legalName": "Google" }

in_ibm.ctx: legalName is the full IBM name with spaces.

$ cat in_ibm.ctx
{ "legalName": " International Business Machines Corporation " }

in_spaces.ctx: legalName contains only spaces.

$ cat in_spaces.ctx
{ "legalName": "   " }

Decision tables in plain Unicode text format:

status_1.dtb

$ cat status_1.dtb
 ┌──────────┐
 │  Status  │
 ├───┬──────┴────┬──────────────────────────────────╥──────────┐
 │ F │ legalName │ matches(legalName, "[a-zA-Z ]+") ║  Status  │
 ╞═══╪═══════════╪══════════════════════════════════╬══════════╡
 │ 1 │ "Google"  │ -                                ║ "vip"    │
 ├───┼───────────┼──────────────────────────────────╫──────────┤
 │ 2 │ -         │ true                             ║ "pass"   │
 ├───┼───────────┼──────────────────────────────────╫──────────┤
 │ 3 │ -         │ -                                ║ "review" │
 └───┴───────────┴──────────────────────────────────╨──────────┘

status_2.dtb

$ cat status_2.dtb
 ┌──────────┐
 │  Status  │
 ├───┬──────┴────╥──────────┐
 │ F │ legalName ║  Status  │
 ╞═══╪═══════════╬══════════╡
 │ 1 │ "Google"  ║ "vip"    │
 ├───┼───────────╫──────────┤
 │ 2 │ ""        ║ "review" │
 ├───┼───────────╫──────────┤
 │ 3 │ -         ║ "pass"   │
 └───┴───────────╨──────────┘

status_3.dtb

$ cat status_3.dtb
 ┌──────────┐
 │  Status  │
 ├───┬──────┴───────────────────────────╥──────────┐
 │ F │             true                 ║  Status  │
 ╞═══╪══════════════════════════════════╬══════════╡
 │ 1 │ legalName = "Google"             ║ "vip"    │
 ├───┼──────────────────────────────────╫──────────┤
 │ 2 │ matches(legalName, "[a-zA-Z ]+") ║ "pass"   │
 ├───┼──────────────────────────────────╫──────────┤
 │ 3 │ -                                ║ "review" │
 └───┴──────────────────────────────────╨──────────┘

status_4.dtb

$ cat status_4.dtb
 ┌──────────┐
 │  Status  │
 ├───┬──────┴─────────────────────────────╥──────────┐
 │ F │             true                   ║  Status  │
 ╞═══╪════════════════════════════════════╬══════════╡
 │ 1 │ legalName = "Google"               ║ "vip"    │
 ├───┼────────────────────────────────────╫──────────┤
 │ 2 │ matches(legalName, "^[a-zA-Z ]+$") ║ "pass"   │
 ├───┼────────────────────────────────────╫──────────┤
 │ 3 │ legalName = ""                     ║ "review" │
 ├───┼────────────────────────────────────╫──────────┤
 │ 4 │ -                                  ║ "reject" │
 └───┴────────────────────────────────────╨──────────┘

DSNTK has a handy command named edt (Evaluate Decision Table) for testing decision tables during design.

$ dsntk edt --help
Evaluate Decision Table

Usage: dsntk edt <INPUT_FILE> <DECTAB_FILE>

Arguments:
  <INPUT_FILE>   File containing input data for evaluated decision table
  <DECTAB_FILE>  File containing decision table to be evaluated

Options:
  -h, --help  Print help

So, let's test all example decision tables against all example input data.

status_1.dtb

$ dsntk edt in_digits.ctx status_1.dtb
"pass"
$ dsntk edt in_empty.ctx status_1.dtb
"review"
$ dsntk edt in_google.ctx status_1.dtb
"vip"
$ dsntk edt in_ibm.ctx status_1.dtb
"pass"
$ dsntk edt in_spaces.ctx status_1.dtb
"pass"

status_2.dtb

$ dsntk edt in_digits.ctx status_2.dtb
"pass"
$ dsntk edt in_empty.ctx status_2.dtb
"review"
$ dsntk edt in_google.ctx status_2.dtb
"vip"
$ dsntk edt in_ibm.ctx status_2.dtb
"pass"
$ dsntk edt in_spaces.ctx status_2.dtb
"pass"

status_3.dtb

$ dsntk edt in_digits.ctx status_3.dtb
"pass"
$ dsntk edt in_empty.ctx status_3.dtb
"review"
$ dsntk edt in_google.ctx status_3.dtb
"vip"
$ dsntk edt in_ibm.ctx status_3.dtb
"pass"
$ dsntk edt in_spaces.ctx status_3.dtb
"pass"

status_4.dtb

$ dsntk edt in_digits.ctx status_4.dtb
"reject"
$ dsntk edt in_empty.ctx status_4.dtb
"review"
$ dsntk edt in_google.ctx status_4.dtb
"vip"
$ dsntk edt in_ibm.ctx status_4.dtb
"pass"
$ dsntk edt in_spaces.ctx status_4.dtb
"pass"
antback commented 7 months ago

Hi @dsntk ,

Thank you very much for such a very good answer. I really appreciate it. Let me check carefully ... :-)

Regards.

dsntk commented 6 months ago

Hi @antback,

I am closing this issue, but feel free to reopen it or comment when needed.

Regards.