dmntk_model_evaluator/
model_definitions.rs

1//! # Model definitions needed for building model evaluator
2
3use crate::errors::err_invalid_item_definition_type;
4use crate::type_ref::type_ref_to_feel_type;
5use dmntk_common::{HRef, Result};
6use dmntk_feel::{Name, QualifiedName};
7use dmntk_model::*;
8use std::collections::HashMap;
9use std::fmt;
10
11/// Types of invocables in DMN model.
12#[derive(Clone)]
13pub enum InvocableType {
14  /// Decision invocable.
15  Decision(
16    /// A key uniquely identifying a decision, see [DefKey] for details.
17    DefKey,
18  ),
19  /// Business knowledge model invocable.
20  BusinessKnowledgeModel(
21    /// A key uniquely identifying a business knowledge model, see [DefKey] for details.
22    DefKey,
23    /// Name of the output variable.
24    Name,
25  ),
26  /// Decision service invocable.
27  DecisionService(
28    /// A key uniquely identifying a decision service, see [DefKey] for details.
29    DefKey,
30  ),
31}
32
33#[derive(Default)]
34pub struct Invocables {
35  items: HashMap<(String, String), InvocableType>,
36}
37
38impl Invocables {
39  pub fn add_decision(&mut self, namespace: String, name: String, def_key: DefKey) {
40    let invocable_type = InvocableType::Decision(def_key);
41    self.items.insert((namespace, name), invocable_type);
42  }
43
44  pub fn add_bkm(&mut self, namespace: String, name: String, def_key: DefKey, output_variable_name: Name) {
45    let invocable_type = InvocableType::BusinessKnowledgeModel(def_key, output_variable_name);
46    self.items.insert((namespace, name), invocable_type);
47  }
48
49  pub fn add_decision_service(&mut self, namespace: String, name: String, def_key: DefKey) {
50    let invocable_type = InvocableType::DecisionService(def_key);
51    self.items.insert((namespace, name), invocable_type);
52  }
53
54  pub fn by_name(&self, namespace: &str, name: &str) -> Option<&InvocableType> {
55    self.items.get(&(namespace.to_string(), name.to_string()))
56  }
57
58  pub fn list(&self) -> Vec<(String, String)> {
59    let mut items = vec![];
60    for (namespace, name) in self.items.keys() {
61      items.push((namespace.clone(), name.clone()));
62    }
63    items.sort();
64    items
65  }
66
67  pub fn len(&self) -> usize {
68    self.items.len()
69  }
70}
71
72/// The key in hash maps for indexing definition artefacts by namespace and identifier.
73///
74/// [DefKey].0 = namespace
75/// [DefKey].1 = identifier
76///
77#[derive(Debug, Clone, Hash, PartialEq, Eq)]
78pub struct DefKey(String, String);
79
80impl DefKey {
81  /// Creates new key based on namespace and identifier.
82  pub fn new(namespace: &str, id: &str) -> Self {
83    Self(namespace.to_string(), id.to_string())
84  }
85}
86
87impl fmt::Display for DefKey {
88  /// Converts [DefKey] to string.
89  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90    write!(f, "{}#{}", self.0, self.1)
91  }
92}
93
94impl From<&DefHRef> for DefKey {
95  fn from(value: &DefHRef) -> Self {
96    Self::new(value.namespace(), value.id())
97  }
98}
99
100impl DefKey {
101  pub fn namespace(&self) -> &str {
102    &self.0
103  }
104  pub fn id(&self) -> &str {
105    &self.1
106  }
107}
108
109/// Information item definition (variable properties).
110pub struct DefInformationItem {
111  /// Variable namespace.
112  namespace: String,
113  /// Variable name.
114  name: Name,
115  /// Variable type reference.
116  type_ref: String,
117}
118
119impl DefInformationItem {
120  /// Creates [DefInformationItem] from [InformationItem].
121  pub fn new(information_item: &InformationItem, imports: &[DefImport]) -> Self {
122    let type_ref_name = Name::from(information_item.type_ref().clone());
123    let qname = QualifiedName::from(type_ref_name);
124    if qname.len() == 2 {
125      // type reference is prefixed with the import name
126      let import_name = qname.first().unwrap(); // unwrap is safe
127      let namespace = get_import_namespace(import_name, imports).unwrap_or(information_item.namespace().to_string());
128      let name = information_item.feel_name().clone();
129      let type_ref = qname.get(1).unwrap().to_string(); // unwrap is safe
130      Self { namespace, name, type_ref }
131    } else {
132      // type reference has no import prefix
133      let namespace = information_item.namespace().to_string();
134      let type_ref = information_item.type_ref().clone();
135      let name = information_item.feel_name().clone();
136      Self { namespace, name, type_ref }
137    }
138  }
139}
140
141impl DefInformationItem {
142  /// Returns information item's namespace.
143  pub fn namespace(&self) -> &str {
144    &self.namespace
145  }
146
147  /// Returns information item's name.
148  pub fn name(&self) -> &Name {
149    &self.name
150  }
151
152  /// Returns a reference to optional type reference.
153  pub fn type_ref(&self) -> &String {
154    &self.type_ref
155  }
156}
157
158pub struct DefInputData {
159  namespace: String,
160  id: String,
161  name: String,
162  variable: DefInformationItem,
163}
164
165impl DefInputData {
166  /// Creates [DefInputData] from [InputData].
167  pub fn new(input_data: &InputData, imports: &[DefImport]) -> Self {
168    Self {
169      namespace: input_data.namespace().to_string(),
170      id: input_data.id().to_string(),
171      name: input_data.name().to_string(),
172      variable: DefInformationItem::new(input_data.variable(), imports),
173    }
174  }
175}
176
177impl DefInputData {
178  /// Returns the namespace.
179  pub fn namespace(&self) -> &str {
180    &self.namespace
181  }
182
183  /// Returns a reference to identifier.
184  pub fn id(&self) -> &str {
185    &self.id
186  }
187
188  /// Returns a reference to name.
189  pub fn name(&self) -> &str {
190    &self.name
191  }
192
193  /// Returns reference to a variable.
194  pub fn variable(&self) -> &DefInformationItem {
195    &self.variable
196  }
197}
198
199pub struct DefItemDefinition {
200  namespace: String,
201  id: String,
202  name: String,
203  feel_name: Name,
204  type_ref: Option<String>,
205  allowed_values: Option<UnaryTests>,
206  item_components: Vec<DefItemDefinition>,
207  function_item: Option<FunctionItem>,
208  is_collection: bool,
209}
210
211impl DefItemDefinition {
212  pub fn new(item_definition: &ItemDefinition) -> Self {
213    Self {
214      namespace: item_definition.namespace().to_string(),
215      id: item_definition.id().to_string(),
216      name: item_definition.name().to_string(),
217      feel_name: item_definition.feel_name().clone(),
218      type_ref: item_definition.type_ref().clone(),
219      allowed_values: item_definition.allowed_values().clone(),
220      item_components: item_definition.item_components().iter().map(DefItemDefinition::new).collect(),
221      function_item: item_definition.function_item().clone(),
222      is_collection: item_definition.is_collection(),
223    }
224  }
225}
226
227impl DefItemDefinition {
228  /// Returns the namespace.
229  pub fn namespace(&self) -> &str {
230    &self.namespace
231  }
232
233  /// Returns the identifier.
234  pub fn id(&self) -> &str {
235    &self.id
236  }
237
238  /// Returns a name.
239  pub fn name(&self) -> &str {
240    &self.name
241  }
242
243  /// Returns a FEEL name.
244  pub fn feel_name(&self) -> &Name {
245    &self.feel_name
246  }
247
248  /// Returns type reference.
249  pub fn type_ref(&self) -> &Option<String> {
250    &self.type_ref
251  }
252
253  /// Returns reference to possible values or ranges of values
254  /// in the base type that are allowed in this [ItemDefinition].
255  pub fn allowed_values(&self) -> &Option<UnaryTests> {
256    &self.allowed_values
257  }
258
259  /// Returns reference to nested [ItemDefinitions](ItemDefinition) that compose this [ItemDefinition].
260  pub fn item_components(&self) -> &Vec<DefItemDefinition> {
261    &self.item_components
262  }
263
264  /// Returns a reference to an optional [FunctionItem] that compose this [ItemDefinition].
265  pub fn function_item(&self) -> &Option<FunctionItem> {
266    &self.function_item
267  }
268
269  /// Returns flag indicating if the actual values are collections of allowed values.
270  pub fn is_collection(&self) -> bool {
271    self.is_collection
272  }
273
274  /// Returns the item definition type.
275  pub fn item_definition_type(&self) -> Result<ItemDefinitionType> {
276    let simple_type_ref = if let Some(type_ref) = self.type_ref() { type_ref_to_feel_type(type_ref) } else { None };
277    let condition = (
278      self.type_ref().is_some(),
279      simple_type_ref.is_some(),
280      !self.item_components().is_empty(),
281      self.is_collection(),
282      self.function_item().is_some(),
283    );
284    match condition {
285      (_, true, false, false, false) => Ok(ItemDefinitionType::SimpleType(simple_type_ref.unwrap().clone())),
286      (true, false, false, false, false) => Ok(ItemDefinitionType::ReferencedType(self.namespace.clone(), self.type_ref().as_ref().unwrap().clone())),
287      (false, false, true, false, false) => Ok(ItemDefinitionType::ComponentType),
288      (_, true, false, true, false) => Ok(ItemDefinitionType::CollectionOfSimpleType(simple_type_ref.unwrap().clone())),
289      (false, false, true, true, false) => Ok(ItemDefinitionType::CollectionOfComponentType),
290      (true, false, false, true, false) => Ok(ItemDefinitionType::CollectionOfReferencedType(
291        self.namespace.clone(),
292        self.type_ref().as_ref().unwrap().clone(),
293      )),
294      (false, false, false, false, true) => Ok(ItemDefinitionType::FunctionType),
295      _ => Err(err_invalid_item_definition_type(self.name())),
296    }
297  }
298}
299
300pub struct DefBusinessKnowledgeModel {
301  namespace: String,
302  id: String,
303  name: String,
304  variable: DefInformationItem,
305  encapsulated_logic: Option<FunctionDefinition>,
306  knowledge_requirements: Vec<DefKnowledgeRequirement>,
307}
308
309impl DefBusinessKnowledgeModel {
310  /// Create [DefBusinessKnowledgeModel] from [BusinessKnowledgeModel].
311  pub fn new(business_knowledge_model: &BusinessKnowledgeModel, imports: &[DefImport]) -> Self {
312    Self {
313      namespace: business_knowledge_model.namespace().to_string(),
314      id: business_knowledge_model.id().to_string(),
315      name: business_knowledge_model.name().to_string(),
316      variable: DefInformationItem::new(business_knowledge_model.variable(), imports),
317      encapsulated_logic: business_knowledge_model.encapsulated_logic().clone(),
318      knowledge_requirements: business_knowledge_model
319        .knowledge_requirements()
320        .iter()
321        .map(|knowledge_requirements| DefKnowledgeRequirement::new(knowledge_requirements, imports))
322        .collect(),
323    }
324  }
325}
326
327impl DefBusinessKnowledgeModel {
328  /// Returns the namespace.
329  pub fn namespace(&self) -> &str {
330    &self.namespace
331  }
332
333  /// Returns an identifier.
334  pub fn id(&self) -> &str {
335    &self.id
336  }
337
338  /// Returns a name.
339  pub fn name(&self) -> &str {
340    &self.name
341  }
342
343  /// Returns an output variable.
344  pub fn variable(&self) -> &DefInformationItem {
345    &self.variable
346  }
347
348  /// Returns reference to a variable for this [BusinessKnowledgeModel].
349  pub fn encapsulated_logic(&self) -> &Option<FunctionDefinition> {
350    &self.encapsulated_logic
351  }
352
353  /// Returns reference to the collection of instances of [KnowledgeRequirement] that compose this [BusinessKnowledgeModel].
354  pub fn knowledge_requirements(&self) -> &Vec<DefKnowledgeRequirement> {
355    &self.knowledge_requirements
356  }
357}
358
359pub struct DefHRef {
360  /// Namespace of the reference, derived from definition or set explicitly.
361  namespace: String,
362  /// Identifier of the referenced element.
363  id: String,
364  /// Name of the import associated with the namespace.
365  import_name: Option<Name>,
366}
367
368impl DefHRef {
369  pub fn new(namespace: &str, href: &HRef, imports: &[DefImport]) -> Self {
370    let namespace = href.namespace().cloned().unwrap_or(namespace.to_string());
371    let import_name = get_import_name(&namespace, imports);
372    Self {
373      namespace,
374      id: href.id().to_string(),
375      import_name,
376    }
377  }
378
379  pub fn namespace(&self) -> &str {
380    &self.namespace
381  }
382
383  pub fn id(&self) -> &str {
384    &self.id
385  }
386
387  pub fn import_name(&self) -> Option<&Name> {
388    self.import_name.as_ref()
389  }
390}
391
392pub struct DefInformationRequirement {
393  required_decision: Option<DefHRef>,
394  required_input: Option<DefHRef>,
395}
396
397impl DefInformationRequirement {
398  pub fn new(information_requirement: &InformationRequirement, imports: &[DefImport]) -> Self {
399    Self {
400      required_decision: information_requirement
401        .required_decision()
402        .as_ref()
403        .map(|href| DefHRef::new(information_requirement.namespace(), href, imports)),
404      required_input: information_requirement
405        .required_input()
406        .as_ref()
407        .map(|href| DefHRef::new(information_requirement.namespace(), href, imports)),
408    }
409  }
410
411  pub fn required_decision(&self) -> Option<&DefHRef> {
412    self.required_decision.as_ref()
413  }
414
415  pub fn required_input(&self) -> Option<&DefHRef> {
416    self.required_input.as_ref()
417  }
418}
419
420pub struct DefKnowledgeRequirement {
421  required_knowledge: DefHRef,
422}
423
424impl DefKnowledgeRequirement {
425  pub fn new(knowledge_requirement: &KnowledgeRequirement, imports: &[DefImport]) -> Self {
426    Self {
427      required_knowledge: DefHRef::new(knowledge_requirement.namespace(), knowledge_requirement.required_knowledge(), imports),
428    }
429  }
430
431  pub fn required_knowledge(&self) -> &DefHRef {
432    &self.required_knowledge
433  }
434}
435
436pub struct DefDecision {
437  namespace: String,
438  id: String,
439  name: String,
440  variable: DefInformationItem,
441  decision_logic: Option<ExpressionInstance>,
442  information_requirements: Vec<DefInformationRequirement>,
443  knowledge_requirements: Vec<DefKnowledgeRequirement>,
444}
445
446impl DefDecision {
447  /// Create [DefDecision] from [Decision].
448  pub fn new(decision: &Decision, imports: &[DefImport]) -> Self {
449    Self {
450      namespace: decision.namespace().to_string(),
451      id: decision.id().to_string(),
452      name: decision.name().to_string(),
453      variable: DefInformationItem::new(decision.variable(), imports),
454      decision_logic: decision.decision_logic().clone(),
455      information_requirements: decision
456        .information_requirements()
457        .iter()
458        .map(|knowledge_requirements| DefInformationRequirement::new(knowledge_requirements, imports))
459        .collect(),
460      knowledge_requirements: decision
461        .knowledge_requirements()
462        .iter()
463        .map(|knowledge_requirements| DefKnowledgeRequirement::new(knowledge_requirements, imports))
464        .collect(),
465    }
466  }
467}
468
469impl DefDecision {
470  /// Returns the namespace.
471  pub fn namespace(&self) -> &str {
472    &self.namespace
473  }
474
475  /// Returns an identifier.
476  pub fn id(&self) -> &str {
477    &self.id
478  }
479
480  /// Returns a name.
481  pub fn name(&self) -> &str {
482    &self.name
483  }
484
485  /// Returns output variable.
486  pub fn variable(&self) -> &DefInformationItem {
487    &self.variable
488  }
489
490  /// Returns a reference to optional [Expression].
491  pub fn decision_logic(&self) -> &Option<ExpressionInstance> {
492    &self.decision_logic
493  }
494
495  /// Returns a reference to collection of [InformationRequirement].
496  pub fn information_requirements(&self) -> &Vec<DefInformationRequirement> {
497    &self.information_requirements
498  }
499
500  /// Returns reference to the collection of instances of [KnowledgeRequirement] that compose this [BusinessKnowledgeModel].
501  pub fn knowledge_requirements(&self) -> &Vec<DefKnowledgeRequirement> {
502    &self.knowledge_requirements
503  }
504}
505
506pub struct DefDecisionService {
507  namespace: String,
508  id: String,
509  name: String,
510  variable: DefInformationItem,
511  input_decisions: Vec<DefHRef>,
512  output_decisions: Vec<DefHRef>,
513  encapsulated_decisions: Vec<DefHRef>,
514  input_data: Vec<DefHRef>,
515}
516
517impl DefDecisionService {
518  /// Creates [DefDecisionService] from [DecisionService].
519  pub fn new(decision_service: &DecisionService, imports: &[DefImport]) -> Self {
520    let namespace = decision_service.namespace();
521    Self {
522      namespace: namespace.to_string(),
523      id: decision_service.id().to_string(),
524      name: decision_service.name().to_string(),
525      variable: DefInformationItem::new(decision_service.variable(), imports),
526      input_decisions: decision_service.input_decisions().iter().map(|href| DefHRef::new(namespace, href, imports)).collect(),
527      output_decisions: decision_service.output_decisions().iter().map(|href| DefHRef::new(namespace, href, imports)).collect(),
528      encapsulated_decisions: decision_service
529        .encapsulated_decisions()
530        .iter()
531        .map(|href| DefHRef::new(namespace, href, imports))
532        .collect(),
533      input_data: decision_service.input_data().iter().map(|href| DefHRef::new(namespace, href, imports)).collect(),
534    }
535  }
536}
537
538impl DefDecisionService {
539  /// Returns the namespace.
540  pub fn namespace(&self) -> &str {
541    &self.namespace
542  }
543
544  /// Returns a reference to identifier.
545  pub fn id(&self) -> &str {
546    &self.id
547  }
548
549  /// Returns a reference to name.
550  pub fn name(&self) -> &str {
551    &self.name
552  }
553
554  /// Returns reference to a variable.
555  pub fn variable(&self) -> &DefInformationItem {
556    &self.variable
557  }
558
559  /// Returns a collection of input [Decision]s for this [DecisionService].
560  pub fn input_decisions(&self) -> &Vec<DefHRef> {
561    &self.input_decisions
562  }
563
564  /// Returns a collection of encapsulated [Decision]s for this [DecisionService].
565  pub fn encapsulated_decisions(&self) -> &Vec<DefHRef> {
566    &self.encapsulated_decisions
567  }
568  /// Returns a collection of output [Decision]s for this [DecisionService].
569  pub fn output_decisions(&self) -> &Vec<DefHRef> {
570    &self.output_decisions
571  }
572
573  /// Returns a collection of [InputData] for this [DecisionService].
574  pub fn input_data(&self) -> &Vec<DefHRef> {
575    &self.input_data
576  }
577}
578
579#[derive(Default)]
580pub struct DefImport {
581  namespace: String,
582  name: Name,
583}
584
585impl DefImport {
586  /// Creates [DefImport] from [Import].
587  pub fn new(import: &Import) -> Self {
588    Self {
589      namespace: import.namespace().to_string(),
590      name: import.feel_name().clone(),
591    }
592  }
593}
594
595/// All definitions needed to build complete model evaluator from DMN model.
596#[derive(Default)]
597pub struct DefDefinitions {
598  /// List of imports.
599  imports: Vec<DefImport>,
600  /// Item definitions.
601  item_definitions: Vec<DefItemDefinition>,
602  /// Input data definitions.
603  input_data: HashMap<DefKey, DefInputData>,
604  /// Business knowledge models.
605  business_knowledge_models: HashMap<DefKey, DefBusinessKnowledgeModel>,
606  /// Decisions.
607  decisions: HashMap<DefKey, DefDecision>,
608  /// Decision services.
609  decision_services: HashMap<DefKey, DefDecisionService>,
610}
611
612impl DefDefinitions {
613  /// Adds definitions from specified model.
614  pub fn add_model(&mut self, definitions: &Definitions) {
615    self.imports.append(&mut definitions.imports().iter().map(DefImport::new).collect());
616    self
617      .item_definitions
618      .append(&mut definitions.item_definitions().iter().map(DefItemDefinition::new).collect());
619    for drg_element in definitions.drg_elements() {
620      match drg_element {
621        DrgElement::InputData(inner) => {
622          self.input_data.insert(DefKey::new(inner.namespace(), inner.id()), DefInputData::new(inner, &self.imports));
623        }
624        DrgElement::BusinessKnowledgeModel(inner) => {
625          self
626            .business_knowledge_models
627            .insert(DefKey::new(inner.namespace(), inner.id()), DefBusinessKnowledgeModel::new(inner, &self.imports));
628        }
629        DrgElement::Decision(inner) => {
630          self.decisions.insert(DefKey::new(inner.namespace(), inner.id()), DefDecision::new(inner, &self.imports));
631        }
632        DrgElement::DecisionService(inner) => {
633          self
634            .decision_services
635            .insert(DefKey::new(inner.namespace(), inner.id()), DefDecisionService::new(inner, &self.imports));
636        }
637        _ => {}
638      }
639    }
640  }
641
642  /// Returns item definitions.
643  pub fn item_definitions(&self) -> &Vec<DefItemDefinition> {
644    &self.item_definitions
645  }
646
647  /// Returns references to decisions.
648  pub fn decisions(&self) -> Vec<&DefDecision> {
649    self.decisions.values().collect()
650  }
651
652  /// Returns an optional reference to [Decision] with specified identifier
653  /// or [None] when such [Decision] was not found among instances of [DrgElement].
654  pub fn decision_by_key(&self, namespace: &str, id: &str) -> Option<&DefDecision> {
655    self.decisions.get(&DefKey::new(namespace, id))
656  }
657
658  /// Returns references to business knowledge models.
659  pub fn business_knowledge_models(&self) -> Vec<&DefBusinessKnowledgeModel> {
660    self.business_knowledge_models.values().collect()
661  }
662
663  /// Returns an optional reference to [BusinessKnowledgeModel] with specified identifier
664  /// or [None] when such [BusinessKnowledgeModel] was not found among instances of [DrgElement].
665  pub fn business_knowledge_model_by_key(&self, namespace: &str, id: &str) -> Option<&DefBusinessKnowledgeModel> {
666    self.business_knowledge_models.get(&DefKey::new(namespace, id))
667  }
668
669  /// Returns references to decision services.
670  pub fn decision_services(&self) -> Vec<&DefDecisionService> {
671    self.decision_services.values().collect()
672  }
673
674  /// Returns an optional reference to [DecisionService] with specified identifier
675  /// or [None] when such [DecisionService] was not found among instances of [DrgElement].
676  pub fn decision_service_by_id(&self, namespace: &str, id: &str) -> Option<&DefDecisionService> {
677    self.decision_services.get(&DefKey::new(namespace, id))
678  }
679
680  /// Returns references to input data instances.
681  pub fn input_data(&self) -> Vec<&DefInputData> {
682    self.input_data.values().collect()
683  }
684
685  /// Returns an optional reference to [InputData] with specified identifier
686  /// or [None] when such [InputData] was not found among
687  /// instances of [DrgElement]).
688  pub fn input_data_by_key(&self, namespace: &str, id: &str) -> Option<&DefInputData> {
689    self.input_data.get(&DefKey::new(namespace, id))
690  }
691}
692
693/// Returns a name of the import for specified namespace.
694fn get_import_name(namespace: &str, imports: &[DefImport]) -> Option<Name> {
695  imports
696    .iter()
697    .filter_map(|def_import| if def_import.namespace == namespace { Some(def_import.name.clone()) } else { None })
698    .collect::<Vec<Name>>()
699    .first()
700    .cloned()
701}
702
703/// Returns a namespace of the import for specified name.
704fn get_import_namespace(name: &Name, imports: &[DefImport]) -> Option<String> {
705  imports
706    .iter()
707    .filter_map(|def_import| if &def_import.name == name { Some(def_import.namespace.clone()) } else { None })
708    .collect::<Vec<String>>()
709    .first()
710    .cloned()
711}