dmntk_examples/
lib.rs

1//! # Examples of decision models and decision tables
2
3mod compatibility;
4pub mod decision_logic;
5pub mod decision_tables;
6mod examples;
7mod full_model;
8pub mod input_data;
9pub mod item_definition;
10
11pub use compatibility::*;
12pub use examples::valid::*;
13pub use examples::*;
14pub use full_model::*;
15
16#[cfg(test)]
17mod utilities {
18  use std::collections::BTreeSet;
19  use std::fmt::Write;
20  use walkdir::WalkDir;
21
22  /// Generates multiple decision table variants.
23  #[test]
24  #[ignore]
25  #[rustfmt::skip]
26  pub fn generate_decision_table_variants() {
27    let mut buffer = String::new();
28    let orientation = ["horizontal", "vertical", "crosstab"];
29    let information_item = ["absent", "present" ];
30    let output_label = ["absent", "present" ];
31    let allowed_values = ["absent", "present"];
32    let inputs = ["absent", "single", "double", "multiple"];
33    let outputs = ["single", "double", "multiple"];
34    let annotations = ["absent", "single", "double", "multiple"];
35    let _ = writeln!(&mut buffer, "┌──────┬─────────────┬─────────────┬─────────┬─────────┬──────────┬──────────┬─────────────┬─────────┬────────┐");
36    let _ = writeln!(&mut buffer, "│  No. │  Preferred  │ Information │ Output  │ Allowed │  Inputs  │ Outputs  │ Annotations │ Example │ Status │");
37    let _ = writeln!(&mut buffer, "│      │ orientation │  item name  │  label  │ values  │          │          │             │         │        │");
38    let _ = writeln!(&mut buffer, "├──────┼─────────────┼─────────────┼─────────┼─────────┼──────────┼──────────┼─────────────┼─────────┼────────┤");
39    let mut counter = 1;
40    for v_decision_table_orientation in orientation {
41      for v_information_item_name in information_item {
42        for v_output_label in output_label {
43          for v_allowed_values in allowed_values {
44            for v_inputs in inputs {
45              for v_outputs in outputs {
46                for v_annotations in annotations {
47                  let _ = writeln!(&mut buffer, "│ {counter:>4} │{v_decision_table_orientation:^13}│{v_information_item_name:^13}│{v_output_label:^9}│{v_allowed_values:^9}│{v_inputs:^10}│{v_outputs:^10}│{v_annotations:^13}│ DT_{counter:04} │        │");
48                  counter += 1;
49                }
50              }
51            }
52          }
53        }
54      }
55    }
56    let _ = writeln!(&mut buffer, "└──────┴─────────────┴─────────────┴─────────┴─────────┴──────────┴──────────┴─────────────┴─────────┴────────┘");
57    println!("{}", buffer);
58    assert_eq!(1157, buffer.lines().count());
59  }
60
61  /// This is a utility function for comparing the number of compatibility test models in this crate
62  /// with the number of compatibility test models in TCK repository.
63  #[test]
64  #[ignore]
65  fn compare_the_number_of_models() {
66    let tck_models = count_models("../../tck/TestCases");
67    let tck_adjusted_models = tck_models
68      .iter()
69      .filter_map(|s| {
70        let segments = s.split('/').collect::<Vec<&str>>();
71        let first_segment = segments[0]
72          .replace("compliance-level-2", "level_2")
73          .replace("compliance-level-3", "level_3")
74          .replace("non-compliant", "non_compliant");
75        let last_segment = segments[2][0..4].to_string();
76        if last_segment.chars().next().unwrap().is_ascii_digit() {
77          Some(format!("{}/{}", first_segment, last_segment))
78        } else {
79          None
80        }
81      })
82      .collect::<BTreeSet<String>>();
83
84    let dmntk_models = count_models("src/compatibility");
85    let dmntk_adjusted_models = dmntk_models
86      .iter()
87      .map(|s| {
88        let segments = s.split('/').collect::<Vec<&str>>();
89        let first_segment = segments[0];
90        let last_segment = segments[1][2..6].to_string();
91        format!("{}/{}", first_segment, last_segment)
92      })
93      .collect::<BTreeSet<String>>();
94
95    let mut all_keys = BTreeSet::new();
96    all_keys.append(&mut tck_adjusted_models.clone());
97    all_keys.append(&mut dmntk_adjusted_models.clone());
98
99    println!("-------------------------------");
100    println!(" Model               TCK  DMNTK");
101    println!("-------------------------------");
102    for key in &all_keys {
103      println!(
104        "{:20}  {:>2}     {:>2}",
105        key,
106        if tck_adjusted_models.contains(key) { "OK" } else { "-" },
107        if dmntk_adjusted_models.contains(key) { "OK" } else { "-" }
108      )
109    }
110  }
111
112  /// Counts DMN models.
113  fn count_models(root_dir: &str) -> BTreeSet<String> {
114    let mut results = BTreeSet::new();
115    for entry_result in WalkDir::new(root_dir).into_iter() {
116      let entry = entry_result.unwrap();
117      let path = entry.path();
118      if path.is_file() && path.extension().is_some_and(|ext| ext == "dmn") {
119        results.insert(path.strip_prefix(root_dir).unwrap().display().to_string());
120      }
121    }
122    results
123  }
124}