dsntk_recognizer/
builder.rs1use crate::errors::*;
4use crate::recognizer::Recognizer;
5use crate::utils::get_allowed_and_default_output_values;
6use crate::{AnnotationClause, AnnotationEntry, DecisionRule, DecisionTable, HitPolicy, InputClause, InputEntry, OutputClause, OutputEntry};
7use dsntk_common::Result;
8
9struct Size {
11 input_clauses_count: usize,
12 input_values_count: usize,
13 output_clauses_count: usize,
14 output_components_count: usize,
15 output_values_count: usize,
16 annotation_clauses_count: usize,
17 rule_count: usize,
18}
19
20fn validate_size(recognizer: &Recognizer) -> Result<Size> {
22 let input_clauses_count = recognizer.input_clause_count;
24 let input_expression_count = recognizer.input_expressions.len();
26 if input_expression_count != input_clauses_count {
27 return Err(err_invalid_size(&format!(
28 "number of input expressions ({input_expression_count}) must be equal to the number of input clauses ({input_clauses_count})"
29 )));
30 }
31 let input_values_count = recognizer.allowed_input_values.len();
33 if input_values_count > 0 && input_values_count != input_clauses_count {
34 return Err(err_invalid_size(&format!(
35 "number of input values ({input_values_count}) must be equal to the number of input clauses ({input_clauses_count})"
36 )));
37 }
38 let output_clauses_count = recognizer.output_clause_count;
40 if output_clauses_count == 0 {
41 return Err(err_invalid_size("decision table must have minimum one output clause"));
42 }
43 let output_components_count = recognizer.output_components.len();
45 if output_clauses_count > 1 {
46 if output_components_count != output_clauses_count {
47 return Err(err_invalid_size(&format!(
48 "number of output components ({output_components_count}) must be equal to the number of output clauses ({output_clauses_count})"
49 )));
50 }
51 } else if output_components_count != 0 {
52 return Err(err_invalid_size("number of output components must be zero"));
53 }
54 let output_values_count = recognizer.allowed_output_values.len();
56 if output_values_count > 0 && output_values_count != output_clauses_count {
57 return Err(err_invalid_size(&format!(
58 "number of output values ({output_values_count}) must be equal to the number of output clauses ({output_clauses_count})"
59 )));
60 }
61 let rule_count = recognizer.rule_count;
63 if rule_count == 0 {
64 return Err(err_invalid_size("decision table must contain minimum one rule"));
65 }
66 let input_entries_row_count = recognizer.input_entries.len();
68 if input_entries_row_count != rule_count {
69 return Err(err_invalid_size(&format!(
70 "number of input entries ({input_entries_row_count}) must be equal to the number of rules ({rule_count})",
71 )));
72 }
73 for (row_index, row) in recognizer.input_entries.iter().enumerate() {
75 if row.len() != input_clauses_count {
76 return Err(err_invalid_size(&format!(
77 "number of input entries ({}) must be equal to the number of input clauses ({input_clauses_count}) in row {row_index}",
78 row.len(),
79 )));
80 }
81 }
82 let output_entries_row_count = recognizer.output_entries.len();
84 if output_entries_row_count != rule_count {
85 return Err(err_invalid_size(&format!(
86 "number of output entries ({output_entries_row_count}) must be equal to the number of rules ({rule_count})"
87 )));
88 }
89 for (row_index, row) in recognizer.output_entries.iter().enumerate() {
91 if row.len() != output_clauses_count {
92 return Err(err_invalid_size(&format!(
93 "number of output entries ({}) must be equal to the number of output clauses ({output_clauses_count}) in row {row_index}",
94 row.len()
95 )));
96 }
97 }
98 let annotation_clauses_count = recognizer.annotation_clause_count;
100 if annotation_clauses_count > 0 {
101 let annotation_entries_row_count = recognizer.annotation_entries.len();
103 if annotation_entries_row_count != rule_count {
104 return Err(err_invalid_size(&format!(
105 "number of annotation entries ({annotation_entries_row_count}) must be equal to the number of rules ({rule_count})"
106 )));
107 }
108 for (row_index, row) in recognizer.annotation_entries.iter().enumerate() {
110 if row.len() != annotation_clauses_count {
111 return Err(err_invalid_size(&format!(
112 "number of annotation entries ({}) must be equal to the number of annotation clauses ({}) in row {}",
113 row.len(),
114 annotation_clauses_count,
115 row_index
116 )));
117 }
118 }
119 }
120 Ok(Size {
121 input_clauses_count,
122 input_values_count,
123 output_clauses_count,
124 output_components_count,
125 output_values_count,
126 annotation_clauses_count,
127 rule_count,
128 })
129}
130
131pub fn from_unicode(text: &str, trace: bool) -> Result<DecisionTable> {
133 let recognizer = Recognizer::recognize(text, trace)?;
135
136 let size = validate_size(&recognizer)?;
138
139 let information_item_name = recognizer.information_item_name.clone();
141
142 let hit_policy = recognizer.hit_policy;
144
145 let aggregation = if let HitPolicy::Collect(built_in_aggregator) = hit_policy {
147 Some(built_in_aggregator)
148 } else {
149 None
150 };
151
152 let preferred_orientation = recognizer.orientation;
154
155 let output_label = recognizer.output_label.clone();
157
158 let mut input_clauses = vec![];
160 for i in 0..size.input_clauses_count {
161 input_clauses.push(InputClause {
162 input_expression: recognizer.input_expressions[i].clone(),
163 allowed_input_values: if size.input_values_count > 0 {
164 recognizer.allowed_input_values[i].clone()
165 } else {
166 None
167 },
168 });
169 }
170
171 let mut output_clauses = vec![];
173 for i in 0..size.output_clauses_count {
174 let output_component_name = if size.output_components_count > 0 {
175 recognizer.output_components[i].clone()
176 } else {
177 output_label.clone()
178 };
179 let (allowed_output_values, default_output_value) = get_allowed_and_default_output_values(&if size.output_values_count > 0 {
180 recognizer.allowed_output_values[i].clone()
181 } else {
182 None
183 });
184 output_clauses.push(OutputClause {
185 output_component_name,
186 allowed_output_values,
187 default_output_value,
188 });
189 }
190
191 let mut annotations = vec![];
193 for i in 0..recognizer.annotation_clause_count {
194 annotations.push(AnnotationClause {
195 name: recognizer.annotations[i].clone(),
196 });
197 }
198
199 let mut rules = vec![];
201 for rule_index in 0..size.rule_count {
202 let mut input_entries = vec![];
203 for column_index in 0..size.input_clauses_count {
204 let input_entry = InputEntry {
205 text: recognizer.input_entries[rule_index][column_index].clone(),
206 };
207 input_entries.push(input_entry);
208 }
209 let mut output_entries = vec![];
210 for column_index in 0..size.output_clauses_count {
211 let output_entry = OutputEntry {
212 text: recognizer.output_entries[rule_index][column_index].clone(),
213 };
214 output_entries.push(output_entry);
215 }
216 let mut annotation_entries = vec![];
217 for column_index in 0..size.annotation_clauses_count {
218 let annotation_entry = AnnotationEntry {
219 text: recognizer.annotation_entries[rule_index][column_index].clone(),
220 };
221 annotation_entries.push(annotation_entry);
222 }
223 rules.push(DecisionRule {
224 input_entries,
225 output_entries,
226 annotation_entries,
227 });
228 }
229
230 Ok(DecisionTable::new(
232 information_item_name,
233 input_clauses,
234 output_clauses,
235 annotations,
236 rules,
237 hit_policy,
238 aggregation,
239 preferred_orientation,
240 output_label,
241 ))
242}