dsntk_model/model.rs
1//! # DMN model
2//!
3//! Model for Decision Requirements Graph (DRG)
4//! depicted in one or more Decision Requirements Diagrams (DRD).
5
6use crate::errors::*;
7use dsntk_common::{gen_id, DsntkError, HRef, Result, Uri};
8use dsntk_feel::{FeelType, Name};
9use std::fmt;
10use std::fmt::Display;
11use std::slice::Iter;
12
13pub enum DmnVersion {
14 V13,
15 V14,
16 V15,
17}
18
19/// [DmnId] defines possible types of unique identifiers in model.
20///
21/// Specification defines this identifier as optional, so when this identifier
22/// is not provided in the model, a new unique UUID identifier is generated.
23/// This SHALL not be conflicting with any other identifier.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum DmnId {
26 /// Identifier was provided in model.
27 Provided(String),
28 /// Identifier was generated during parsing (not provided in model).
29 Generated(String),
30}
31
32/// [DmnElement] is the abstract superclass for the Decision Model elements.
33/// It provides the optional attributes `id`, `description` and `label`,
34/// which other elements will inherit.
35pub trait DmnElement {
36 /// Namespace the element belongs to.
37 fn namespace(&self) -> &str;
38 /// Name of the model the element was defined in.
39 fn model_name(&self) -> &str;
40 /// Returns a reference to identifier for this [DmnElement].
41 /// This identifier SHALL be unique within its containing [Definitions] element.
42 fn id(&self) -> &String;
43 /// Returns a reference to optional identifier for this [DmnElement].
44 fn opt_id(&self) -> Option<&String>;
45 /// Returns reference to optional description of this [DmnElement].
46 fn description(&self) -> &Option<String>;
47 /// Returns reference to optional alternative short description of this [DmnElement].
48 fn label(&self) -> &Option<String>;
49 /// Returns reference to attached additional elements to any [DmnElement].
50 fn extension_elements(&self) -> &Vec<ExtensionElement>;
51 /// Returns reference to attached named extended attributes and model associations to any [DmnElement].
52 fn extension_attributes(&self) -> &Vec<ExtensionAttribute>;
53}
54
55/// [NamedElement] adds attribute `name` to [DmnElement].
56/// `name` attribute is required for [NamedElement].
57pub trait NamedElement: DmnElement {
58 /// Returns the name of this [NamedElement].
59 fn name(&self) -> &str;
60 /// Returns the `FEEL` name for this element.
61 fn feel_name(&self) -> &Name;
62}
63
64/// [Expression] is an abstract class that describes the logic
65/// by which a modeled decision shall be made, or pieces of that logic.
66pub trait Expression {
67 /// Optional namespace-prefixed name of the base type of this [Expression].
68 fn type_ref(&self) -> &Option<String>;
69}
70
71/// [FeelTypedElement] adds the `FEEL` type attributes to element.
72pub trait FeelTypedElement {
73 /// Returns the optional `FEEL` type for this element.
74 fn feel_type(&self) -> &Option<FeelType>;
75 /// Sets `FEEL` type for this element.
76 fn set_feel_type(&mut self, feel_type: FeelType);
77}
78
79/// [RequiredTypeRef] adds the required type reference to element.
80pub trait RequiredTypeRef {
81 /// Namespace-prefixed name of the base type of the implementor.
82 fn type_ref(&self) -> &str;
83}
84
85/// [RequiredVariable] adds the required reference to [InformationItem].
86pub trait RequiredVariable {
87 /// Returns the reference to [InformationItem].
88 fn variable(&self) -> &InformationItem;
89}
90
91/// `Invocable` is used to model the inputs of a decision whose values
92/// are defined outside the decision model.
93pub trait Invocable: DmnElement + NamedElement + RequiredVariable {}
94
95/// The abstract class [BusinessContextElement].
96///
97/// The abstract class [BusinessContextElement], and its concrete specializations
98/// [PerformanceIndicator] and [OrganizationUnit] are placeholders,
99/// anticipating a definition to be adopted from other OMG metamodels,
100/// such as OMG OSM when it is further developed.
101pub trait BusinessContextElement: NamedElement {
102 /// The URI of this [BusinessContextElement].
103 fn uri(&self) -> &Option<String>;
104}
105
106/// The [ExtensionElement] contains element from other
107/// metamodels inside any [DmnElement].
108///
109/// Not used, prepared for further development.
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct ExtensionElement;
112
113/// The [ExtensionAttribute] element.
114///
115/// The [ExtensionAttribute] element contains an [ExtensionElement]
116/// or a reference to an [ExtensionElement] from another metamodel.
117/// An [ExtensionAttribute] also has a name
118/// to define the role or purpose of the associated element.
119///
120/// Not used, prepared for further development.
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct ExtensionAttribute;
123
124/// Enumeration of concrete instances of [BusinessContextElement].
125#[derive(Debug, Clone)]
126pub enum BusinessContextElementInstance {
127 PerformanceIndicator(PerformanceIndicator),
128 OrganizationUnit(OrganizationUnit),
129}
130
131/// [PerformanceIndicator] is a placeholder, anticipating a definition to be
132/// adopted from other OMG metamodels, such as OMG OSM when it is further developed.
133#[named_element]
134#[dmn_element]
135#[business_context_element]
136#[derive(Debug, Clone)]
137pub struct PerformanceIndicator {
138 /// Collection of [Decision] that impact this [PerformanceIndicator].
139 /// This attribute stores references
140 pub(crate) impacting_decisions: Vec<HRef>,
141}
142
143impl PerformanceIndicator {
144 pub fn impacting_decisions(&self) -> &Vec<HRef> {
145 &self.impacting_decisions
146 }
147}
148
149/// [OrganizationUnit] is a placeholder, anticipating a definition to be
150/// adopted from other OMG metamodels, such as OMG OSM when it is further developed.
151#[named_element]
152#[dmn_element]
153#[business_context_element]
154#[derive(Debug, Clone)]
155pub struct OrganizationUnit {
156 /// Collection of [Decision] that are made by this [OrganizationUnit].
157 pub(crate) decisions_made: Vec<HRef>,
158 /// Collection of [Decision] that are owned by this [OrganizationUnit].
159 pub(crate) decisions_owned: Vec<HRef>,
160}
161
162impl OrganizationUnit {
163 pub fn decisions_made(&self) -> &Vec<HRef> {
164 &self.decisions_made
165 }
166 pub fn decisions_owned(&self) -> &Vec<HRef> {
167 &self.decisions_owned
168 }
169}
170
171/// In DMN model, the [DrgElement] is the abstract superclass for all DMN elements.
172///
173/// All DMN elements are contained within [Definitions] and that have a graphical
174/// representation in a DRD. This enumeration specifies the list
175/// of [DRGElements](DrgElement) contained in [Definitions].
176#[derive(Debug, Clone)]
177#[allow(clippy::large_enum_variant)]
178pub enum DrgElement {
179 Decision(Decision),
180 InputData(InputData),
181 BusinessKnowledgeModel(BusinessKnowledgeModel),
182 DecisionService(DecisionService),
183 KnowledgeSource(KnowledgeSource),
184}
185
186/// Enumeration of specific requirements.
187pub enum Requirement {
188 Information(InformationRequirement),
189 Knowledge(KnowledgeRequirement),
190 Authority(AuthorityRequirement),
191}
192
193/// [Definitions] element is the outermost containing object
194/// for all elements of a DMN decision model.
195/// It defines the scope of visibility and the namespace
196/// for all contained elements.
197#[named_element]
198#[dmn_element]
199#[derive(Debug, Clone)]
200pub struct Definitions {
201 /// This attribute identifies the expression language used in
202 /// [LiteralExpressions](LiteralExpression) within the scope
203 /// of this [Definitions]. The _Default_ is FEEL.
204 /// This value **MAY** be overridden on each individual [LiteralExpression].
205 /// The language **SHALL** be specified in a URI format.
206 pub(crate) expression_language: Option<Uri>,
207 /// This attribute identifies the type language used in
208 /// [LiteralExpressions](LiteralExpression) within the scope
209 /// of this [Definitions]. The _Default_ is FEEL.
210 /// This value **MAY** be overridden on each individual [ItemDefinition].
211 /// The language **SHALL** be specified in a URI format.
212 pub(crate) type_language: Option<Uri>,
213 /// Name of the tool used to export the XML serialization.
214 pub(crate) exporter: Option<String>,
215 /// Version of the tool used to export the XML serialization.
216 pub(crate) exporter_version: Option<String>,
217 /// Container for the instances of [ItemDefinition] that are contained in this [Definitions].
218 pub(crate) item_definitions: Vec<ItemDefinition>,
219 /// Container for the instances of [DrgElement] that are contained in this [Definitions].
220 pub(crate) drg_elements: Vec<DrgElement>,
221 /// Container for the instances of [BusinessContextElement] that are contained in this [Definitions].
222 pub(crate) business_context_elements: Vec<BusinessContextElementInstance>,
223 /// Container used to import externally defined elements and make them available
224 /// for use by elements in this [Definitions].
225 pub(crate) imports: Vec<Import>,
226 /// Optional diagram interchange information contained within this [Definitions].
227 pub(crate) dmndi: Option<Dmndi>,
228}
229
230impl Definitions {
231 /// Returns the reference to optional expression language used within the scope of this [Definitions].
232 pub fn expression_language(&self) -> &Option<String> {
233 &self.expression_language
234 }
235
236 /// Returns reference to the type language used within the scope of this [Definitions].
237 pub fn type_language(&self) -> &Option<String> {
238 &self.type_language
239 }
240
241 /// Returns reference to the name of the tool used to export the XML serialization.
242 pub fn exporter(&self) -> &Option<String> {
243 &self.exporter
244 }
245
246 /// Returns reference to the version of the tool used to export the XML serialization.
247 pub fn exporter_version(&self) -> &Option<String> {
248 &self.exporter_version
249 }
250
251 /// Returns reference to the container of instances of [ItemDefinition] contained in this [Definitions].
252 pub fn item_definitions(&self) -> &Vec<ItemDefinition> {
253 &self.item_definitions
254 }
255
256 /// Returns reference to the container of instances of [Import] contained in this [Definitions].
257 pub fn imports(&self) -> &Vec<Import> {
258 &self.imports
259 }
260
261 /// Returns reference to optional [Dmndi] container.
262 pub fn dmndi(&self) -> &Option<Dmndi> {
263 &self.dmndi
264 }
265
266 /// Returns reference to [DrgElements](DrgElement) container.
267 pub fn drg_elements(&self) -> Iter<DrgElement> {
268 self.drg_elements.iter()
269 }
270
271 /// Returns all decision definitions.
272 pub fn decisions(&self) -> Vec<Decision> {
273 self
274 .drg_elements
275 .iter()
276 .filter_map(|drg_element| {
277 if let DrgElement::Decision(decision) = drg_element {
278 Some(decision.clone())
279 } else {
280 None
281 }
282 })
283 .collect()
284 }
285
286 /// Returns all business knowledge model definitions.
287 pub fn business_knowledge_models(&self) -> Vec<BusinessKnowledgeModel> {
288 self
289 .drg_elements
290 .iter()
291 .filter_map(|drg_element| {
292 if let DrgElement::BusinessKnowledgeModel(bkm) = drg_element {
293 Some(bkm.clone())
294 } else {
295 None
296 }
297 })
298 .collect()
299 }
300
301 /// Returns all decision services definitions.
302 pub fn decision_services(&self) -> Vec<DecisionService> {
303 self
304 .drg_elements
305 .iter()
306 .filter_map(|drg_element| {
307 if let DrgElement::DecisionService(decision_service) = drg_element {
308 Some(decision_service.clone())
309 } else {
310 None
311 }
312 })
313 .collect()
314 }
315
316 /// Returns all knowledge source definitions.
317 pub fn knowledge_sources(&self) -> Vec<&KnowledgeSource> {
318 self
319 .drg_elements
320 .iter()
321 .filter_map(|drg_element| {
322 if let DrgElement::KnowledgeSource(knowledge_source) = drg_element {
323 Some(knowledge_source)
324 } else {
325 None
326 }
327 })
328 .collect()
329 }
330
331 /// Returns all input data definitions.
332 pub fn input_data(&self) -> Vec<InputData> {
333 self
334 .drg_elements
335 .iter()
336 .filter_map(|drg_element| {
337 if let DrgElement::InputData(input_data) = drg_element {
338 Some(input_data.clone())
339 } else {
340 None
341 }
342 })
343 .collect()
344 }
345
346 /// Returns performance indicators.
347 pub fn performance_indicators(&self) -> Vec<&PerformanceIndicator> {
348 self
349 .business_context_elements
350 .iter()
351 .filter_map(|item| match item {
352 BusinessContextElementInstance::PerformanceIndicator(performance_indicator) => Some(performance_indicator),
353 _ => None,
354 })
355 .collect()
356 }
357
358 /// Returns organisation units.
359 pub fn organisation_units(&self) -> Vec<&OrganizationUnit> {
360 self
361 .business_context_elements
362 .iter()
363 .filter_map(|item| match item {
364 BusinessContextElementInstance::OrganizationUnit(organisation_unit) => Some(organisation_unit),
365 _ => None,
366 })
367 .collect()
368 }
369
370 /// Returns decision with specified identifier.
371 pub fn get_decision(&self, id: &str) -> Option<&Decision> {
372 for drg_element in &self.drg_elements {
373 if let DrgElement::Decision(decision) = drg_element {
374 if decision.id() == id {
375 return Some(decision);
376 }
377 }
378 }
379 None
380 }
381
382 /// Returns input data with specified identifier.
383 pub fn get_input_data(&self, id: &str) -> Option<&InputData> {
384 for drg_element in &self.drg_elements {
385 if let DrgElement::InputData(input_data) = drg_element {
386 if input_data.id() == id {
387 return Some(input_data);
388 }
389 }
390 }
391 None
392 }
393
394 /// Returns business knowledge model with specified identifier.
395 pub fn get_business_knowledge_model(&self, id: &str) -> Option<&BusinessKnowledgeModel> {
396 for drg_element in &self.drg_elements {
397 if let DrgElement::BusinessKnowledgeModel(business_knowledge_model) = drg_element {
398 if business_knowledge_model.id() == id {
399 return Some(business_knowledge_model);
400 }
401 }
402 }
403 None
404 }
405
406 /// Returns knowledge source with specified identifier.
407 pub fn get_knowledge_source(&self, id: &str) -> Option<&KnowledgeSource> {
408 for drg_element in &self.drg_elements {
409 if let DrgElement::KnowledgeSource(knowledge_source) = drg_element {
410 if knowledge_source.id() == id {
411 return Some(knowledge_source);
412 }
413 }
414 }
415 None
416 }
417
418 /// Returns a requirement with specified identifier.
419 pub fn get_requirement(&self, id: &str) -> Option<Requirement> {
420 for drg_element in &self.drg_elements {
421 match drg_element {
422 DrgElement::Decision(decision) => {
423 for knowledge_requirement in &decision.knowledge_requirements {
424 if knowledge_requirement.id() == id {
425 return Some(Requirement::Knowledge(knowledge_requirement.clone()));
426 }
427 }
428 for information_requirement in &decision.information_requirements {
429 if information_requirement.id() == id {
430 return Some(Requirement::Information(information_requirement.clone()));
431 }
432 }
433 for authority_requirement in &decision.authority_requirements {
434 if authority_requirement.id() == id {
435 return Some(Requirement::Authority(authority_requirement.clone()));
436 }
437 }
438 }
439 DrgElement::BusinessKnowledgeModel(business_knowledge_model) => {
440 for knowledge_requirement in &business_knowledge_model.knowledge_requirements {
441 if knowledge_requirement.id() == id {
442 return Some(Requirement::Knowledge(knowledge_requirement.clone()));
443 }
444 }
445 for authority_requirement in &business_knowledge_model.authority_requirements {
446 if authority_requirement.id() == id {
447 return Some(Requirement::Authority(authority_requirement.clone()));
448 }
449 }
450 }
451 DrgElement::KnowledgeSource(knowledge_source) => {
452 for authority_requirement in &knowledge_source.authority_requirements {
453 if authority_requirement.id() == id {
454 return Some(Requirement::Authority(authority_requirement.clone()));
455 }
456 }
457 }
458 _ => {}
459 }
460 }
461 None
462 }
463}
464
465#[named_element]
466#[dmn_element]
467#[derive(Debug, Clone, PartialEq)]
468pub struct InformationItem {
469 /// Qualified name of the type of this [InformationItem].
470 pub(crate) type_ref: String,
471 /// Optional `FEEL` type of this [InformationItem].
472 pub(crate) feel_type: Option<FeelType>,
473}
474
475impl InformationItem {
476 /// Returns qualified name of the type of this [InformationItem].
477 pub fn type_ref(&self) -> &String {
478 &self.type_ref
479 }
480}
481
482impl FeelTypedElement for InformationItem {
483 /// Returns a reference to optional `FEEL` type of this element.
484 fn feel_type(&self) -> &Option<FeelType> {
485 &self.feel_type
486 }
487 /// Sets the `FEEL` type for this element.
488 fn set_feel_type(&mut self, feel_type: FeelType) {
489 self.feel_type = Some(feel_type);
490 }
491}
492
493/// [InputData] is used to model the inputs of a decision whose values
494/// are defined outside the decision model.
495#[named_element]
496#[dmn_element]
497#[derive(Debug, Clone)]
498pub struct InputData {
499 /// The instance of [InformationItem] that stores the result of this [InputData].
500 pub(crate) variable: InformationItem,
501}
502
503impl RequiredVariable for InputData {
504 /// Returns reference to a variable for this [BusinessKnowledgeModel].
505 fn variable(&self) -> &InformationItem {
506 &self.variable
507 }
508}
509
510/// `Import` class is used when referencing external elements.
511///
512/// These elements can either be a DMN [DRGElement](DrgElement) or [ItemDefinition]
513/// instances contained in other [Definitions] elements, or non-DMN elements,
514/// such as an XML Schema or a PMML file.
515#[named_element]
516#[dmn_element]
517#[derive(Debug, Clone, PartialEq, Eq)]
518pub struct Import {
519 /// Specifies the style of import associated with this [Import].
520 pub(crate) import_type: String,
521 /// Identifies the location of the imported element.
522 pub(crate) location_uri: Option<String>,
523}
524
525impl Import {
526 /// Returns reference to the import type for this [Import].
527 pub fn import_type(&self) -> &str {
528 &self.import_type
529 }
530
531 /// Returns reference to the optional location URI for this [Import].
532 pub fn location_uri(&self) -> &Option<String> {
533 &self.location_uri
534 }
535
536 /// Returns reference to the namespace of this [Import].
537 pub fn namespace(&self) -> &str {
538 &self.namespace
539 }
540}
541
542/// An enumeration of concrete instances of abstract [Expression], which are:
543/// - [Conditional],
544/// - [Context],
545/// - [DecisionTable],
546/// - [Every],
547/// - [Filter],
548/// - [For],
549/// - [FunctionDefinition],
550/// - [Invocation],
551/// - [List],
552/// - [LiteralExpression],
553/// - [Relation],
554/// - [Some].
555#[derive(Debug, Clone, PartialEq)]
556pub enum ExpressionInstance {
557 Conditional(Box<Conditional>),
558 Context(Box<Context>),
559 DecisionTable(Box<DecisionTable>),
560 Every(Box<Every>),
561 Filter(Box<Filter>),
562 For(Box<For>),
563 FunctionDefinition(Box<FunctionDefinition>),
564 Invocation(Box<Invocation>),
565 List(Box<List>),
566 LiteralExpression(Box<LiteralExpression>),
567 Relation(Box<Relation>),
568 Some(Box<Some>),
569}
570
571/// A [Context] is composed of any number of model context entries, which are instances of [ContextEntry].
572#[dmn_element]
573#[expression]
574#[derive(Debug, Clone, PartialEq)]
575pub struct Context {
576 /// This attribute lists the instances of [ContextEntry] that compose this [Context].
577 pub(crate) context_entries: Vec<ContextEntry>,
578}
579
580impl Context {
581 /// Return a reference to context entries that compose this [Context].
582 pub fn context_entries(&self) -> &Vec<ContextEntry> {
583 &self.context_entries
584 }
585}
586
587/// The class [ContextEntry] is used to model `FEEL` context entries when a context is modeled as a [Context] element.
588#[derive(Debug, Clone, PartialEq)]
589pub struct ContextEntry {
590 /// The instance of [InformationItem] that is contained in this [ContextEntry],
591 /// and whose name is the key in the modeled context entry.
592 pub variable: Option<InformationItem>,
593 /// The instance of [Expression] that is the expression in this [ContextEntry].
594 pub value: ExpressionInstance,
595}
596
597/// [LiteralExpression] is used to model a value expression whose value
598/// is specified by text in some specified expression language.
599#[dmn_element]
600#[expression]
601#[derive(Debug, Clone, PartialEq, Eq)]
602pub struct LiteralExpression {
603 /// The text of this [LiteralExpression].
604 /// It SHALL be a valid expression in the `expression_language`.
605 pub(crate) text: Option<String>,
606 /// Identifies the expression language used in this [LiteralExpression].
607 pub(crate) expression_language: Option<String>,
608 /// The instance of [ImportedValue](Import) that specifies
609 /// where the text of this [LiteralExpression] is located.
610 pub(crate) imported_values: Option<Import>,
611}
612
613impl LiteralExpression {
614 pub fn text(&self) -> &Option<String> {
615 &self.text
616 }
617
618 pub fn expression_language(&self) -> Option<String> {
619 self.expression_language.clone()
620 }
621
622 pub fn imported_values(&self) -> Option<Import> {
623 self.imported_values.clone()
624 }
625}
626
627/// [Invocation] is a mechanism for the evaluation of value expressions.
628///
629/// [Invocation] is a mechanism that permits the evaluation of one value expression
630/// – the invoked expression – inside another value expression
631/// – the invoking expression – by binding locally the input variables of the invoked
632/// expression to values inside the invoking expression.
633#[dmn_element]
634#[expression]
635#[derive(Debug, Clone, PartialEq)]
636pub struct Invocation {
637 /// An expression whose value is a function.
638 pub(crate) called_function: ExpressionInstance,
639 /// Instances of [Binding] used to bind the formal parameters of the called function in this [Invocation].
640 pub(crate) bindings: Vec<Binding>,
641}
642
643impl Invocation {
644 /// Returns a reference to called function which is an instance of [Expression].
645 pub fn called_function(&self) -> &ExpressionInstance {
646 &self.called_function
647 }
648 /// Returns a reference to the collection of binding instances.
649 pub fn bindings(&self) -> &Vec<Binding> {
650 &self.bindings
651 }
652}
653
654#[derive(Debug, Clone, PartialEq)]
655pub struct Binding {
656 /// The [InformationItem] on which the `calledFunction` of the owning
657 /// instance of [Invocation] depends that is bound by this [Binding].
658 pub(crate) parameter: InformationItem,
659 /// The instance of [Expression] to which the parameter in this [Binding] is
660 /// bound when the owning instance of [Invocation] is evaluated.
661 pub(crate) binding_formula: Option<ExpressionInstance>,
662}
663
664impl Binding {
665 /// Returns a reference to parameter.
666 pub fn parameter(&self) -> &InformationItem {
667 &self.parameter
668 }
669 /// Returns a reference to binding formula.
670 pub fn binding_formula(&self) -> &Option<ExpressionInstance> {
671 &self.binding_formula
672 }
673}
674
675/// [Decision]
676#[named_element]
677#[dmn_element]
678#[derive(Debug, Clone)]
679pub struct Decision {
680 /// A natural language question that characterizes the [Decision],
681 /// such that the output of the [Decision] is an answer to the question.
682 pub(crate) question: Option<String>,
683 /// A natural language description of the answers allowed for the question
684 /// such as `Yes/No`, a list of allowed values, a range of numeric values etc.
685 pub(crate) allowed_answers: Option<String>,
686 /// The instance of [InformationItem] that stores the result of this [Decision].
687 pub(crate) variable: InformationItem,
688 /// The instance of the [Expression] for the [Decision].
689 pub(crate) decision_logic: Option<ExpressionInstance>,
690 /// Collection of the instances of [InformationRequirement] that compose this [Decision].
691 pub(crate) information_requirements: Vec<InformationRequirement>,
692 /// Collection of the instances of [KnowledgeRequirement] that compose this [Decision].
693 pub(crate) knowledge_requirements: Vec<KnowledgeRequirement>,
694 /// Collection of the instances of [AuthorityRequirement] that compose this [Decision].
695 pub(crate) authority_requirements: Vec<AuthorityRequirement>,
696 //TODO add the following:
697 // supported_objectives
698 // impacted_performance_indicator
699 // decision_maker
700 // decision_owner
701 // using_processes
702 // using_tasks
703}
704
705impl Decision {
706 /// Returns a reference to a natural language question that characterizes the [Decision].
707 pub fn question(&self) -> &Option<String> {
708 &self.question
709 }
710 /// Returns a reference to a natural language description of the answers allowed for the question defined in this [Decision].
711 pub fn allowed_answers(&self) -> &Option<String> {
712 &self.allowed_answers
713 }
714 /// Return a reference to a variable that stores the result of this [Decision].
715 pub fn variable(&self) -> &InformationItem {
716 &self.variable
717 }
718 /// Returns a reference to optional [Expression].
719 pub fn decision_logic(&self) -> &Option<ExpressionInstance> {
720 &self.decision_logic
721 }
722 /// Returns a reference to collection of [InformationRequirement].
723 pub fn information_requirements(&self) -> &Vec<InformationRequirement> {
724 &self.information_requirements
725 }
726 /// Returns a reference to collection of [KnowledgeRequirement].
727 pub fn knowledge_requirements(&self) -> &Vec<KnowledgeRequirement> {
728 &self.knowledge_requirements
729 }
730 /// Returns a reference to collection of [AuthorityRequirement].
731 pub fn authority_requirements(&self) -> &Vec<AuthorityRequirement> {
732 &self.authority_requirements
733 }
734}
735
736/// The class [InformationRequirement] is used to model an information requirement,
737/// as represented by a plain arrow in a DRD.
738#[dmn_element]
739#[derive(Debug, Clone)]
740pub struct InformationRequirement {
741 /// Reference to [Decision] that this [InformationRequirement] associates
742 /// with its containing [Decision] element.
743 pub(crate) required_decision: Option<HRef>,
744 /// Reference to [InputData] that this [InformationRequirement] associates
745 /// with its containing [Decision] element.
746 pub(crate) required_input: Option<HRef>,
747}
748
749impl InformationRequirement {
750 /// Returns reference to optional URI pointing a [Decision].
751 pub fn required_decision(&self) -> &Option<HRef> {
752 &self.required_decision
753 }
754
755 /// Returns reference to optional URI pointing an [InputData].
756 pub fn required_input(&self) -> &Option<HRef> {
757 &self.required_input
758 }
759}
760
761/// The class [KnowledgeRequirement] is used to model a knowledge requirement,
762/// as represented by a dashed arrow in a DRD.
763#[dmn_element]
764#[derive(Debug, Clone)]
765pub struct KnowledgeRequirement {
766 /// Reference to [Invocable] that this [KnowledgeRequirement] associates with
767 /// its containing [Decision] or [BusinessKnowledgeModel] element.
768 pub(crate) required_knowledge: HRef,
769}
770
771impl KnowledgeRequirement {
772 /// Returns a reference to the [Invocable].
773 pub fn required_knowledge(&self) -> &HRef {
774 &self.required_knowledge
775 }
776}
777
778/// The class [AuthorityRequirement] is used to model an authority requirement,
779/// as represented by an arrow drawn with a dashed line and a filled circular head in a DRD
780#[dmn_element]
781#[derive(Debug, Clone)]
782pub struct AuthorityRequirement {
783 /// The instance of [KnowledgeSource] that this [AuthorityRequirement] associates
784 /// with its containing [KnowledgeSource], [Decision] or [BusinessKnowledgeModel] element.
785 pub(crate) required_authority: Option<HRef>,
786 /// The instance of [Decision] that this [AuthorityRequirement] associates
787 /// with its containing [KnowledgeSource] element.
788 pub(crate) required_decision: Option<HRef>,
789 /// The instance of [InputData] that this [AuthorityRequirement] associates
790 /// with its containing [KnowledgeSource] element.
791 pub(crate) required_input: Option<HRef>,
792}
793
794impl AuthorityRequirement {
795 /// Returns reference to optional [KnowledgeSource].
796 pub fn required_authority(&self) -> &Option<HRef> {
797 &self.required_authority
798 }
799 /// Returns reference to optional [Decision].
800 pub fn required_decision(&self) -> &Option<HRef> {
801 &self.required_decision
802 }
803 /// Returns reference to optional [InputData].
804 pub fn required_input(&self) -> &Option<HRef> {
805 &self.required_input
806 }
807}
808
809/// The class [KnowledgeSource] is used to model authoritative knowledge sources in a decision model.
810/// In a DRD, an instance of [KnowledgeSource] is represented by a `knowledge source` diagram element.
811#[named_element]
812#[dmn_element]
813#[derive(Debug, Clone)]
814pub struct KnowledgeSource {
815 /// Collection of the instances of [AuthorityRequirement] that compose this [Decision].
816 pub(crate) authority_requirements: Vec<AuthorityRequirement>,
817}
818
819impl KnowledgeSource {
820 /// Returns a reference to collection of [AuthorityRequirement].
821 pub fn authority_requirements(&self) -> &Vec<AuthorityRequirement> {
822 &self.authority_requirements
823 }
824}
825
826/// A business knowledge model.
827///
828/// A business knowledge model has an abstract part, representing reusable,
829/// invocable decision logic, and a concrete part, which mandates that the decision logic
830/// must be a single FEEL boxed function definition.
831#[named_element]
832#[dmn_element]
833#[derive(Debug, Clone)]
834pub struct BusinessKnowledgeModel {
835 /// Variable that is bound to the function defined by the [FunctionDefinition] for this [BusinessKnowledgeModel].
836 pub(crate) variable: InformationItem,
837 /// The function that encapsulates the logic encapsulated by this [BusinessKnowledgeModel].
838 pub(crate) encapsulated_logic: Option<FunctionDefinition>,
839 /// This attribute lists the instances of [KnowledgeRequirement] that compose this [BusinessKnowledgeModel].
840 pub(crate) knowledge_requirements: Vec<KnowledgeRequirement>,
841 /// This attribute lists the instances of [AuthorityRequirement] that compose this [BusinessKnowledgeModel].
842 pub(crate) authority_requirements: Vec<AuthorityRequirement>,
843}
844
845impl BusinessKnowledgeModel {
846 /// Returns reference to a variable for this [BusinessKnowledgeModel].
847 pub fn encapsulated_logic(&self) -> &Option<FunctionDefinition> {
848 &self.encapsulated_logic
849 }
850 /// Returns reference to the collection of instances of [KnowledgeRequirement] that compose this [BusinessKnowledgeModel].
851 pub fn knowledge_requirements(&self) -> &Vec<KnowledgeRequirement> {
852 &self.knowledge_requirements
853 }
854 /// Returns reference to the collection of instances of [AuthorityRequirement] that compose this [BusinessKnowledgeModel].
855 pub fn authority_requirements(&self) -> &Vec<AuthorityRequirement> {
856 &self.authority_requirements
857 }
858}
859
860impl RequiredVariable for BusinessKnowledgeModel {
861 /// Returns reference to a variable for this [BusinessKnowledgeModel].
862 fn variable(&self) -> &InformationItem {
863 &self.variable
864 }
865}
866
867/// The [DecisionService] class is used to define named decision services
868/// against the decision model contained in an instance of [Definitions].
869#[named_element]
870#[dmn_element]
871#[derive(Debug, Clone)]
872pub struct DecisionService {
873 /// Variable for this [DecisionService].
874 pub(crate) variable: InformationItem,
875 /// Collection of references to the instances of [Decision] required to be output by this [DecisionService].
876 pub(crate) output_decisions: Vec<HRef>,
877 /// Collection of references to the instances of [Decision] to be encapsulated in this [DecisionService].
878 pub(crate) encapsulated_decisions: Vec<HRef>,
879 /// Collection of references to the instances of [Decision] required as input by this [DecisionService].
880 pub(crate) input_decisions: Vec<HRef>,
881 /// Collection of references to the instances of [InputData] required as input by this [DecisionService].
882 pub(crate) input_data: Vec<HRef>,
883}
884
885impl DecisionService {
886 /// Returns a reference to collection of references to input [Decision]s for this [DecisionService].
887 pub fn input_decisions(&self) -> &Vec<HRef> {
888 &self.input_decisions
889 }
890 /// Returns a reference to collection of references to encapsulated [Decision]s for this [DecisionService].
891 pub fn encapsulated_decisions(&self) -> &Vec<HRef> {
892 &self.encapsulated_decisions
893 }
894 /// Returns a reference to collection of references to output [Decision]s for this [DecisionService].
895 pub fn output_decisions(&self) -> &Vec<HRef> {
896 &self.output_decisions
897 }
898 /// Returns a reference to collection of references to [InputData] for this [DecisionService].
899 pub fn input_data(&self) -> &Vec<HRef> {
900 &self.input_data
901 }
902}
903
904impl RequiredVariable for DecisionService {
905 /// Returns reference to a variable for this [DecisionService].
906 fn variable(&self) -> &InformationItem {
907 &self.variable
908 }
909}
910
911/// Item definition types.
912#[derive(Debug, Clone, PartialEq)]
913pub enum ItemDefinitionType {
914 SimpleType(FeelType),
915 ReferencedType(String, String),
916 ComponentType,
917 CollectionOfSimpleType(FeelType),
918 CollectionOfReferencedType(String, String),
919 CollectionOfComponentType,
920 FunctionType,
921}
922
923/// [ItemDefinition] is used to model the inputs of a decision,
924/// whose values are defined outside the decision model.
925#[named_element]
926#[dmn_element]
927#[expression]
928#[derive(Debug, Clone)]
929pub struct ItemDefinition {
930 /// This attribute identifies the type language used to specify the base
931 /// type of this [ItemDefinition]. This value overrides the type
932 /// language specified in the [Definitions] element. The default is `FEEL`.
933 /// The language `SHALL` be specified in URI format.
934 pub(crate) type_language: Option<String>,
935 /// This attribute contains `FEEL` built-in type only when the `type_language` attribute
936 /// is `FEEL` and the `type_ref` attribute defines one of the built-in `FEEL` types.
937 pub(crate) feel_type: Option<FeelType>,
938 /// Possible values or ranges of values in the base type that are allowed in this [ItemDefinition].
939 pub(crate) allowed_values: Option<UnaryTests>,
940 /// Defines zero or more nested [ItemDefinitions](ItemDefinition) that compose this [ItemDefinition].
941 pub(crate) item_components: Vec<ItemDefinition>,
942 /// Setting this flag to true indicates that the actual values defined by
943 /// this [ItemDefinition] are collections of allowed values.
944 /// The default value is [false].
945 pub(crate) is_collection: bool,
946 /// Describes an optional [FunctionItem] that compose this [ItemDefinition].
947 pub(crate) function_item: Option<FunctionItem>,
948}
949
950impl ItemDefinition {
951 /// Returns reference to the type language used within the scope of this [ItemDefinition].
952 pub fn type_language(&self) -> &Option<String> {
953 &self.type_language
954 }
955 /// Returns reference to possible values or ranges of values
956 /// in the base type that are allowed in this [ItemDefinition].
957 pub fn allowed_values(&self) -> &Option<UnaryTests> {
958 &self.allowed_values
959 }
960 /// Returns reference to nested [ItemDefinitions](ItemDefinition) that compose this [ItemDefinition].
961 pub fn item_components(&self) -> &Vec<ItemDefinition> {
962 &self.item_components
963 }
964 /// Returns mutable reference to nested [ItemDefinitions](ItemDefinition) that compose this [ItemDefinition].
965 pub fn item_components_mut(&mut self) -> &mut Vec<ItemDefinition> {
966 &mut self.item_components
967 }
968 /// Returns flag indicating if the actual values are collections of allowed values.
969 pub fn is_collection(&self) -> bool {
970 self.is_collection
971 }
972 /// Returns a reference to optional `FEEL` type.
973 pub fn feel_type(&self) -> &Option<FeelType> {
974 &self.feel_type
975 }
976 /// Sets the `FEEL` type for this element.
977 pub fn set_feel_type(&mut self, feel_type: FeelType) {
978 self.feel_type = Some(feel_type);
979 }
980 /// Returns a reference to an optional [FunctionItem] that compose this [ItemDefinition].
981 pub fn function_item(&self) -> &Option<FunctionItem> {
982 &self.function_item
983 }
984}
985
986/// [UnaryTests] is used to model a boolean test, where the argument
987/// to be tested is implicit or denoted with a **?**.
988/// Test is specified by text in some specified expression language.
989#[derive(Debug, Clone)]
990pub struct UnaryTests {
991 /// The text of this [UnaryTests].
992 /// It SHALL be a valid expression in the expressionLanguage.
993 pub(crate) text: Option<String>,
994 /// This attribute identifies the expression language used in this [UnaryTests].
995 /// This value overrides the expression language specified for the containing
996 /// instance of DecisionRequirementDiagram.
997 /// The language SHALL be specified in a URI format.
998 pub(crate) expression_language: Option<String>,
999}
1000
1001impl UnaryTests {
1002 /// Returns reference to optional text of this [UnaryTests].
1003 pub fn text(&self) -> &Option<String> {
1004 &self.text
1005 }
1006 /// Returns reference to optional expression language used in this [UnaryTests].
1007 pub fn expression_language(&self) -> &Option<String> {
1008 &self.expression_language
1009 }
1010}
1011
1012/// [FunctionItem] defines the signature of a function:
1013/// the parameters and the output type of the function.
1014#[derive(Debug, Clone)]
1015pub struct FunctionItem {
1016 /// Reference to output type of the function.
1017 pub(crate) output_type_ref: Option<String>,
1018 /// Function parameters as [InformationItems](InformationItem).
1019 pub(crate) parameters: Vec<InformationItem>,
1020}
1021
1022impl FunctionItem {
1023 /// Returns reference to output type of function.
1024 pub fn output_type_ref(&self) -> &Option<String> {
1025 &self.output_type_ref
1026 }
1027 /// Returns reference to function parameters defined
1028 /// as collection of [InformationItems](InformationItem).
1029 pub fn parameters(&self) -> &Vec<InformationItem> {
1030 &self.parameters
1031 }
1032}
1033
1034/// Defines the type of the [FunctionDefinition].
1035/// The default value is `FEEL`. Supported values also include `Java` and `PMML`.
1036#[derive(Debug, Clone, PartialEq, Eq)]
1037pub enum FunctionKind {
1038 Feel,
1039 Java,
1040 Pmml,
1041}
1042
1043/// [FunctionItem] defines the signature of a function:
1044/// the parameters and the output type of the function.
1045#[dmn_element]
1046#[expression]
1047#[derive(Debug, Clone, PartialEq)]
1048pub struct FunctionDefinition {
1049 /// Container for instances of [InformationItem] that are the parameters of this [FunctionDefinition].
1050 pub(crate) formal_parameters: Vec<InformationItem>,
1051 /// The instance of [Expression] that is the body in this [FunctionDefinition].
1052 pub(crate) body: Option<ExpressionInstance>,
1053 /// Type of this [FunctionDefinition], the default value is FEEL.
1054 pub(crate) kind: FunctionKind,
1055}
1056
1057impl FunctionDefinition {
1058 /// Returns reference to container of [InformationItem] of this [FunctionDefinition].
1059 pub fn formal_parameters(&self) -> &Vec<InformationItem> {
1060 &self.formal_parameters
1061 }
1062 /// Returns reference to [Expression] that is the body in this [FunctionDefinition].
1063 pub fn body(&self) -> &Option<ExpressionInstance> {
1064 &self.body
1065 }
1066 /// Returns the type of this [FunctionDefinition].
1067 pub fn kind(&self) -> &FunctionKind {
1068 &self.kind
1069 }
1070}
1071
1072/// A [Relation] is convenient a shorthand for a list of similar contexts.
1073///
1074/// A [Relation] has a column instead of repeated `ContextEntry`s,
1075/// and a `List` is used for every row, with one of the `List`’s
1076/// expression for each column value.
1077#[dmn_element]
1078#[expression]
1079#[derive(Debug, Clone, PartialEq)]
1080pub struct Relation {
1081 /// This attribute lists the instances of [List] that are the rows in this [Relation].
1082 pub(crate) rows: Vec<List>,
1083 /// This attributes lists the instances of [InformationItem] that define the columns in this [Relation].
1084 pub(crate) columns: Vec<InformationItem>,
1085}
1086
1087impl Relation {
1088 /// Returns a reference to collection of relation's rows.
1089 pub fn rows(&self) -> &Vec<List> {
1090 &self.rows
1091 }
1092 /// Returns a reference to collection of relation's columns.
1093 pub fn columns(&self) -> &Vec<InformationItem> {
1094 &self.columns
1095 }
1096}
1097
1098/// A [List] is simply a list of elements, which are instances of [Expression]s.
1099#[dmn_element]
1100#[expression]
1101#[derive(Debug, Clone, PartialEq)]
1102pub struct List {
1103 /// This attribute lists the instances of [Expression] that are the elements of this [List].
1104 pub(crate) elements: Vec<ExpressionInstance>,
1105}
1106
1107impl List {
1108 /// Returns a reference to collection of list's elements.
1109 pub fn elements(&self) -> &Vec<ExpressionInstance> {
1110 &self.elements
1111 }
1112}
1113
1114/// A [Conditional] is a representation of a visual way to express an if statement.
1115#[dmn_element]
1116#[expression]
1117#[derive(Debug, Clone, PartialEq)]
1118pub struct Conditional {
1119 /// This attribute holds the expression that is evaluated by the conditional expression.
1120 pub(crate) if_expression: ChildExpression,
1121 /// This attribute holds the expression that will be evaluated when the condition in the if statement evaluates to `true`.
1122 pub(crate) then_expression: ChildExpression,
1123 /// This attribute holds the expression that will be evaluated when the condition in the if statement evaluates to `false`.
1124 pub(crate) else_expression: ChildExpression,
1125}
1126
1127impl Conditional {
1128 pub fn if_expression(&self) -> &ChildExpression {
1129 &self.if_expression
1130 }
1131
1132 pub fn then_expression(&self) -> &ChildExpression {
1133 &self.then_expression
1134 }
1135
1136 pub fn else_expression(&self) -> &ChildExpression {
1137 &self.else_expression
1138 }
1139}
1140
1141/// A [Filter] is a visual way to express list filtering.
1142#[dmn_element]
1143#[expression]
1144#[derive(Debug, Clone, PartialEq)]
1145pub struct Filter {
1146 /// This attribute holds the expression that is evaluated as the collection to be filtered.
1147 pub(crate) in_expression: ChildExpression,
1148 /// This attribute holds the expression that is used to filter the collection.
1149 pub(crate) match_expression: ChildExpression,
1150}
1151
1152impl Filter {
1153 pub fn in_expression(&self) -> &ChildExpression {
1154 &self.in_expression
1155 }
1156
1157 pub fn match_expression(&self) -> &ChildExpression {
1158 &self.match_expression
1159 }
1160}
1161
1162/// A [For] is a visual representation of a loop.
1163#[dmn_element]
1164#[expression]
1165#[derive(Debug, Clone, PartialEq)]
1166pub struct For {
1167 /// This attribute holds name of the iterator variable that will be populated at each iteration.
1168 pub(crate) iterator_variable: String,
1169 /// This attribute holds the expression that is evaluated as the collection to be processed.
1170 pub(crate) in_expression: TypedChildExpression,
1171 /// This attribute holds the expression that is evaluated to create the new collection that will be returned.
1172 pub(crate) return_expression: ChildExpression,
1173}
1174
1175impl For {
1176 pub fn iterator_variable(&self) -> &String {
1177 &self.iterator_variable
1178 }
1179
1180 pub fn in_expression(&self) -> &TypedChildExpression {
1181 &self.in_expression
1182 }
1183
1184 pub fn return_expression(&self) -> &ChildExpression {
1185 &self.return_expression
1186 }
1187}
1188
1189/// A [Every] is a visual representation of an expression where all
1190/// `satisfies` needs to be true for it to return true.
1191#[dmn_element]
1192#[expression]
1193#[derive(Debug, Clone, PartialEq)]
1194pub struct Every {
1195 /// This attribute holds name of the iterator variable that will be populated at each iteration.
1196 pub(crate) iterator_variable: String,
1197 /// This attribute holds the expression that is evaluated as the collection to be processed.
1198 pub(crate) in_expression: TypedChildExpression,
1199 /// This attribute holds the expression that is evaluated to determine if the current item satisfies a condition.
1200 pub(crate) satisfies_expression: ChildExpression,
1201}
1202
1203impl Every {
1204 pub fn iterator_variable(&self) -> &String {
1205 &self.iterator_variable
1206 }
1207
1208 pub fn in_expression(&self) -> &TypedChildExpression {
1209 &self.in_expression
1210 }
1211
1212 pub fn satisfies_expression(&self) -> &ChildExpression {
1213 &self.satisfies_expression
1214 }
1215}
1216
1217/// A [Some] is a visual representation of an expression where at least one of the
1218/// `satisfies` needs to be true for it to return true.
1219#[dmn_element]
1220#[expression]
1221#[derive(Debug, Clone, PartialEq)]
1222pub struct Some {
1223 /// This attribute holds name of the iterator variable that will be populated at each iteration.
1224 pub(crate) iterator_variable: String,
1225 /// This attribute holds the expression that is evaluated as the collection to be processed.
1226 pub(crate) in_expression: TypedChildExpression,
1227 /// This attribute holds the expression that is evaluated to determine if the current item satisfies a condition.
1228 pub(crate) satisfies_expression: ChildExpression,
1229}
1230
1231impl Some {
1232 pub fn iterator_variable(&self) -> &String {
1233 &self.iterator_variable
1234 }
1235
1236 pub fn in_expression(&self) -> &TypedChildExpression {
1237 &self.in_expression
1238 }
1239
1240 pub fn satisfies_expression(&self) -> &ChildExpression {
1241 &self.satisfies_expression
1242 }
1243}
1244
1245#[derive(Debug, Clone, PartialEq)]
1246pub struct ChildExpression {
1247 /// Optional identifier of this [ChildExpression].
1248 pub(crate) id: DmnId,
1249 /// The instance of [Expression] trait that is the expression in this [ChildExpression].
1250 pub(crate) value: ExpressionInstance,
1251}
1252
1253impl ChildExpression {
1254 pub fn id(&self) -> &DmnId {
1255 &self.id
1256 }
1257
1258 pub fn value(&self) -> &ExpressionInstance {
1259 &self.value
1260 }
1261}
1262
1263#[expression]
1264#[derive(Debug, Clone, PartialEq)]
1265pub struct TypedChildExpression {
1266 /// Optional identifier of this [TypedChildExpression].
1267 pub(crate) id: DmnId,
1268 /// The instance of [Expression] trait that is the expression in this [TypedChildExpression].
1269 pub(crate) value: ExpressionInstance,
1270}
1271
1272impl TypedChildExpression {
1273 pub fn id(&self) -> &DmnId {
1274 &self.id
1275 }
1276
1277 pub fn value(&self) -> &ExpressionInstance {
1278 &self.value
1279 }
1280}
1281
1282/// Decision table.
1283#[dmn_element]
1284#[expression]
1285#[derive(Debug, Clone, PartialEq, Eq)]
1286pub struct DecisionTable {
1287 /// Information item name, for which the decision table is its value expression.
1288 /// This is usually the name of the decision or the name of business knowledge model for
1289 /// which the decision table provides the decision logic.
1290 pub(crate) information_item_name: Option<String>,
1291 /// List of instances of input clause that compose this decision table.
1292 pub(crate) input_clauses: Vec<InputClause>,
1293 /// List of instances of output clause that compose this decision table.
1294 pub(crate) output_clauses: Vec<OutputClause>,
1295 /// List of instances of rule annotation clause that compose this decision table.
1296 pub(crate) annotations: Vec<RuleAnnotationClause>,
1297 /// List of instances of decision rule that compose this decision table.
1298 pub(crate) rules: Vec<DecisionRule>,
1299 /// Hit policy associated with the instance of the decision table.
1300 pub(crate) hit_policy: HitPolicy,
1301 /// Optional aggregation type when the hit policy is `COLLECT`.
1302 pub(crate) aggregation: Option<BuiltinAggregator>,
1303 /// Preferred representation of the instance of the decision table.
1304 pub(crate) preferred_orientation: DecisionTableOrientation,
1305 /// Optional output label for the description of the decision table output,
1306 /// may be the same as the name of the information item for which the
1307 /// decision table is the value expression.
1308 pub(crate) output_label: Option<String>,
1309}
1310
1311impl Display for DecisionTable {
1312 /// Implements [Display] trait for [DecisionTable].
1313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1314 let mut buffer = String::new();
1315 buffer.push_str("Decision table:\n");
1316 buffer.push_str(format!(">> preferred orientation: {}\n", self.preferred_orientation).as_str());
1317 buffer.push_str(">> information item name: ");
1318 if let Some(text) = &self.information_item_name {
1319 buffer.push_str(format!("\n'{text}'\n").as_str());
1320 } else {
1321 buffer.push_str("none\n");
1322 }
1323 buffer.push_str(format!(">> hit policy: {}\n", self.hit_policy).as_str());
1324 buffer.push_str(">> aggregation: ");
1325 if let Some(aggregation) = &self.aggregation {
1326 buffer.push_str(format!("{aggregation}\n").as_str());
1327 } else {
1328 buffer.push_str("none\n");
1329 }
1330 buffer.push_str(">> output label: ");
1331 if let Some(text) = &self.output_label {
1332 buffer.push_str(format!("\n'{text}'\n").as_str());
1333 } else {
1334 buffer.push_str("none\n");
1335 }
1336 write!(f, "{buffer}")
1337 }
1338}
1339
1340impl DecisionTable {
1341 /// Creates a new decision table.
1342 #[allow(clippy::too_many_arguments)]
1343 pub fn new(
1344 information_item_name: Option<String>,
1345 input_clauses: Vec<InputClause>,
1346 output_clauses: Vec<OutputClause>,
1347 annotations: Vec<RuleAnnotationClause>,
1348 rules: Vec<DecisionRule>,
1349 hit_policy: HitPolicy,
1350 aggregation: Option<BuiltinAggregator>,
1351 preferred_orientation: DecisionTableOrientation,
1352 output_label: Option<String>,
1353 ) -> Self {
1354 Self {
1355 namespace: "".to_string(),
1356 model_name: "".to_string(),
1357 id: DmnId::Generated(gen_id()),
1358 description: None,
1359 label: None,
1360 extension_elements: vec![],
1361 extension_attributes: vec![],
1362 type_ref: None,
1363 information_item_name,
1364 input_clauses,
1365 output_clauses,
1366 annotations,
1367 rules,
1368 hit_policy,
1369 aggregation,
1370 preferred_orientation,
1371 output_label,
1372 }
1373 }
1374
1375 /// Returns the information item name.
1376 pub fn information_item_name(&self) -> &Option<String> {
1377 &self.information_item_name
1378 }
1379
1380 /// Returns an iterator over input clauses.
1381 pub fn input_clauses(&self) -> Iter<InputClause> {
1382 self.input_clauses.iter()
1383 }
1384
1385 /// Returns an iterator over output clauses.
1386 pub fn output_clauses(&self) -> Iter<OutputClause> {
1387 self.output_clauses.iter()
1388 }
1389
1390 /// Returns an iterator over annotations.
1391 pub fn annotations(&self) -> Iter<RuleAnnotationClause> {
1392 self.annotations.iter()
1393 }
1394
1395 /// Returns an iterator over the rules.
1396 pub fn rules(&self) -> Iter<DecisionRule> {
1397 self.rules.iter()
1398 }
1399
1400 /// Returns the [HitPolicy] of this decision table.
1401 pub fn hit_policy(&self) -> HitPolicy {
1402 self.hit_policy
1403 }
1404
1405 /// Returns the aggregation when the [HitPolicy] is `COLLECT`.
1406 pub fn aggregation(&self) -> &Option<BuiltinAggregator> {
1407 &self.aggregation
1408 }
1409
1410 /// Returns preferred orientation for this decision table.
1411 pub fn preferred_orientation(&self) -> &DecisionTableOrientation {
1412 &self.preferred_orientation
1413 }
1414
1415 /// Return an output label.
1416 pub fn output_label(&self) -> &Option<String> {
1417 &self.output_label
1418 }
1419
1420 /// Returns `true` when allowed input and/or allowed output values are present in decision table.
1421 pub fn allowed_values_present(&self) -> bool {
1422 for input_clause in &self.input_clauses {
1423 if input_clause.allowed_input_values.is_some() {
1424 return true;
1425 }
1426 }
1427 for output_clause in &self.output_clauses {
1428 if output_clause.allowed_output_values.is_some() {
1429 return true;
1430 }
1431 }
1432 false
1433 }
1434}
1435
1436/// Orientation of the decision table.
1437#[derive(Debug, Clone, PartialEq, Eq)]
1438pub enum DecisionTableOrientation {
1439 /// Decision table is presented horizontally, rules are presented as rows.
1440 RuleAsRow,
1441 /// Decision table is presented vertically, rules are presented as columns.
1442 RuleAsColumn,
1443 /// Decision table is presented as crosstab, rules are composed of two input dimensions.
1444 CrossTable,
1445}
1446
1447impl Display for DecisionTableOrientation {
1448 /// Implements [Display] trait for [DecisionTableOrientation].
1449 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1450 match self {
1451 DecisionTableOrientation::RuleAsRow => write!(f, "Rule-as-Row"),
1452 DecisionTableOrientation::RuleAsColumn => write!(f, "Rule-as-Column"),
1453 DecisionTableOrientation::CrossTable => write!(f, "CrossTable"),
1454 }
1455 }
1456}
1457
1458impl TryFrom<&str> for DecisionTableOrientation {
1459 type Error = DsntkError;
1460 /// Tries to construct a decision table orientation from its text representation.
1461 fn try_from(value: &str) -> Result<Self, Self::Error> {
1462 match value.trim() {
1463 "Rule-as-Row" => Ok(DecisionTableOrientation::RuleAsRow),
1464 "Rule-as-Column" => Ok(DecisionTableOrientation::RuleAsColumn),
1465 "CrossTable" => Ok(DecisionTableOrientation::CrossTable),
1466 other => Err(err_invalid_decision_table_orientation(other)),
1467 }
1468 }
1469}
1470
1471/// Hit policy.
1472#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1473pub enum HitPolicy {
1474 /// `UNIQUE` hit policy. No overlapping rules are allowed, only single rule can be matched.
1475 /// This is the default value for hit policy. Crosstab decision tables may have only unique hit policy.
1476 Unique,
1477 /// `ANY` hit policy. Rules may overlap, but all matching rules show equal output entries.
1478 /// If matching rules have non-equal output entries, this policy is incorrect and the result is undefined.
1479 Any,
1480 /// `PRIORITY` hit policy. Multiple rules can match, with different output entries for each output.
1481 /// This policy returns matching rule with the highest priority. Output priorities are specified
1482 /// in the ordered list of output values, in decreasing order of priority.
1483 Priority,
1484 /// `FIRST` hit policy...
1485 First,
1486 /// `COLLECT` hit policy...
1487 Collect(BuiltinAggregator),
1488 /// `OUTPUT ORDER` hit policy...
1489 OutputOrder,
1490 /// `RULE ORDER` hit policy...
1491 RuleOrder,
1492}
1493
1494impl Display for HitPolicy {
1495 /// Implements [Display] trait for [HitPolicy].
1496 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1497 match self {
1498 HitPolicy::Unique => write!(f, "U"),
1499 HitPolicy::Any => write!(f, "A"),
1500 HitPolicy::Priority => write!(f, "P"),
1501 HitPolicy::First => write!(f, "F"),
1502 HitPolicy::Collect(aggregator) => write!(f, "{aggregator}"),
1503 HitPolicy::OutputOrder => write!(f, "O"),
1504 HitPolicy::RuleOrder => write!(f, "R"),
1505 }
1506 }
1507}
1508
1509impl TryFrom<&str> for HitPolicy {
1510 type Error = DsntkError;
1511 /// Creates a hit policy from text.
1512 fn try_from(value: &str) -> Result<Self, Self::Error> {
1513 match value.trim() {
1514 "U" => Ok(HitPolicy::Unique),
1515 "A" => Ok(HitPolicy::Any),
1516 "P" => Ok(HitPolicy::Priority),
1517 "F" => Ok(HitPolicy::First),
1518 "R" => Ok(HitPolicy::RuleOrder),
1519 "O" => Ok(HitPolicy::OutputOrder),
1520 "C" => Ok(HitPolicy::Collect(BuiltinAggregator::List)),
1521 "C+" => Ok(HitPolicy::Collect(BuiltinAggregator::Sum)),
1522 "C#" => Ok(HitPolicy::Collect(BuiltinAggregator::Count)),
1523 "C<" => Ok(HitPolicy::Collect(BuiltinAggregator::Min)),
1524 "C>" => Ok(HitPolicy::Collect(BuiltinAggregator::Max)),
1525 other => Err(err_invalid_decision_table_hit_policy(other)),
1526 }
1527 }
1528}
1529
1530/// Aggregator function for `COLLECT` [hit policy](HitPolicy).
1531#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1532pub enum BuiltinAggregator {
1533 /// The result of the decision table is a list of output entries.
1534 List,
1535 /// The result of the decision table is the number of outputs.
1536 Count,
1537 /// The result of the decision table is the sum of all the outputs.
1538 Sum,
1539 /// The result of the decision table is the smallest value of all the outputs.
1540 Min,
1541 /// The result of the decision table is the largest value of all the outputs.
1542 Max,
1543}
1544
1545impl Display for BuiltinAggregator {
1546 /// Implements [Display] trait for [BuiltinAggregator].
1547 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1548 write!(
1549 f,
1550 "{}",
1551 match self {
1552 BuiltinAggregator::List => "C",
1553 BuiltinAggregator::Count => "C#",
1554 BuiltinAggregator::Sum => "C+",
1555 BuiltinAggregator::Min => "C<",
1556 BuiltinAggregator::Max => "C>",
1557 }
1558 )
1559 }
1560}
1561
1562#[derive(Debug, Clone, PartialEq, Eq)]
1563pub struct InputClause {
1564 /// The subject of this input clause, text representation of unary tests.
1565 pub input_expression: String,
1566 /// Optional unary tests that constrain the result of input expression of this input clause.
1567 pub allowed_input_values: Option<String>,
1568}
1569
1570#[derive(Debug, Clone, PartialEq, Eq)]
1571pub struct OutputClause {
1572 /// Type reference may specify the type to be used as decision table's output when more than one output clause is present.
1573 pub type_ref: Option<String>,
1574 /// The name of the output component when the decision table contains more than one output clause.
1575 pub name: Option<String>,
1576 /// Unary tests that constrain the result of output entries corresponding to this output clause.
1577 pub allowed_output_values: Option<String>,
1578 /// Default output expression, selected in incomplete table when no rules match for the decision table.
1579 pub default_output_entry: Option<String>,
1580}
1581
1582#[derive(Debug, Clone, PartialEq, Eq)]
1583pub struct RuleAnnotationClause {
1584 /// Name that is used as the name of the rule annotation column of the containing decision table.
1585 pub name: String,
1586}
1587
1588#[derive(Debug, Clone, PartialEq, Eq)]
1589pub struct DecisionRule {
1590 /// Ordered list of input entries that compose this decision rule.
1591 pub input_entries: Vec<InputEntry>,
1592 /// Ordered list of output entries that compose this decision rule.
1593 pub output_entries: Vec<OutputEntry>,
1594 /// Ordered list of rule annotations that compose this decision rule.
1595 pub annotation_entries: Vec<AnnotationEntry>,
1596}
1597
1598#[derive(Debug, Clone, PartialEq, Eq)]
1599pub struct InputEntry {
1600 /// Text representation of unary test that composes this input entry.
1601 pub text: String,
1602}
1603
1604#[derive(Debug, Clone, PartialEq, Eq)]
1605pub struct OutputEntry {
1606 /// Text representation of literal expression that composes this output entry.
1607 pub text: String,
1608}
1609
1610#[derive(Debug, Clone, PartialEq, Eq)]
1611pub struct AnnotationEntry {
1612 /// Text representing this rule annotation.
1613 pub text: String,
1614}
1615
1616/// [Dmndi] is a container for the shared [DmnStyle](DmnStyle)s
1617/// and all [DmnDiagram](DmnDiagram)s defined in [Definitions].
1618#[derive(Debug, Clone)]
1619pub struct Dmndi {
1620 /// A list of shared [DmnStyle] that can be referenced
1621 /// by all [DmnDiagram] and [DmnDiagramElement].
1622 pub styles: Vec<DmnStyle>,
1623 /// A list of [DmnDiagram].
1624 pub diagrams: Vec<DmnDiagram>,
1625}
1626
1627/// Defines possible elements of [DmnDiagramElement].
1628#[derive(Debug, Clone)]
1629pub enum DmnDiagramElement {
1630 DmnShape(DmnShape),
1631 DmnEdge(DmnEdge),
1632}
1633
1634/// [DmnDiagram] is the container of [DmnDiagramElement] ([DmnShape] (s) and [DmnEdge] (s)).
1635/// [DmnDiagram] cannot include other [DmnDiagrams](DmnDiagram).
1636#[derive(Debug, Clone, Default)]
1637pub struct DmnDiagram {
1638 /// [DmnDiagram] id.
1639 pub id: Option<String>,
1640 /// The name of the diagram. Default is empty [String].
1641 pub name: Option<String>,
1642 /// The documentation of the diagram. Default is empty [String].
1643 pub documentation: String,
1644 /// The resolution of the diagram expressed in user units per inch. Default is 300.
1645 pub resolution: f64,
1646 /// A list of [DmnDiagramElement] ([DmnShape] and [DmnEdge]) that are depicted in this diagram.
1647 pub diagram_elements: Vec<DmnDiagramElement>,
1648 /// A reference to a [DmnStyle] defined in the [Dmndi] that serves as the default styling
1649 /// of the [DmnDiagramElement] in this [DmnDiagram].
1650 pub shared_style: Option<String>,
1651 /// A [DmnStyle] that defines the default styling for this diagram.
1652 /// Properties defined in that style override the ones in the 'sharedStyle'.
1653 pub local_style: Option<DmnStyle>,
1654 /// The size of this diagram. If not specified, the [DmnDiagram] is unbounded.
1655 pub size: Option<DcDimension>,
1656}
1657
1658/// [DmnShape] represents a [Decision], a [BusinessKnowledgeModel], an [InputData] element,
1659/// a [KnowledgeSource], a [DecisionService] or a [TextAnnotation] that is depicted on the diagram.
1660#[derive(Debug, Clone)]
1661pub struct DmnShape {
1662 /// Unique identifier of this [DmnShape].
1663 pub id: Option<String>,
1664 /// The [DcBounds] of the shape relative to the origin of its parent [DmnDiagram]. The [DcBounds] MUST be specified.
1665 pub bounds: DcBounds,
1666 /// A reference to a [Decision], a [BusinessKnowledgeModel], an [InputData] element,
1667 /// a [KnowledgeSource], a [DecisionService] or a [TextAnnotation] MUST be specified.
1668 pub dmn_element_ref: Option<String>,
1669 /// If the [DmnShape] depicts an [InputData] element then this attribute is used to determine
1670 /// if the [InputData] is listed on the [Decision] element (true) or drawn as separate notational elements in the DRD (false).
1671 pub is_listed_input_data: bool,
1672 /// If the [DmnShape] depicts a [DecisionService], this attribute references a [DmnDecisionServiceDividerLine] that defines,
1673 /// where the [DmnShape] is divided into two parts by a straight solid line.
1674 /// This can be the case when a [DmnShape] depicts a [DecisionService],
1675 /// where the set of output decisions is smaller than the set of encapsulated decisions.
1676 /// The start and end waypoints of the `decisionServiceDividerLine` **MUST** be on the border of the [DmnShape].
1677 pub decision_service_divider_line: Option<DmnDecisionServiceDividerLine>,
1678 /// If the [DmnShape] depicts a [DecisionService], this attribute indicates
1679 /// if it should be depicted expanded (`false`) or collapsed (`true`).
1680 /// Default is `false`.
1681 pub is_collapsed: bool,
1682 /// A reference to a [DmnStyle] defined in the [Dmndi].
1683 pub shared_style: Option<String>,
1684 /// A [DmnStyle] that defines the styling for this element.
1685 pub local_style: Option<DmnStyle>,
1686 /// An optional label when this [DmnElement] has a visible text label.
1687 pub label: Option<DmnLabel>,
1688}
1689
1690/// Struct defines line inside [DecisionService].
1691#[derive(Debug, Clone)]
1692pub struct DmnDecisionServiceDividerLine {
1693 pub id: Option<String>,
1694 /// A list of points relative to the origin of its parent [DmnDiagram] that specifies
1695 /// the connected line segments of the edge. At least two (2) waypoint`s MUST be specified.
1696 /// Waypoint must be on the border of the [DmnShape].
1697 pub way_points: Vec<DcPoint>,
1698 /// A reference to a [DmnStyle] defined in the [Dmndi].
1699 pub shared_style: Option<String>,
1700 /// A [DmnStyle] that defines the styling for this element.
1701 pub local_style: Option<DmnStyle>,
1702}
1703
1704#[derive(Debug, Clone)]
1705pub struct DmnEdge {
1706 pub id: Option<String>,
1707 /// A list of points relative to the origin of its parent [DmnDiagram] that specifies
1708 /// the connected line segments of the edge. At least two (2) waypoints MUST be specified.
1709 pub way_points: Vec<DcPoint>,
1710 /// A reference to a [InformationRequirement], [KnowledgeRequirement],
1711 /// [AuthorityRequirement] or an [Association], MUST be specified.
1712 pub dmn_element_ref: Option<String>,
1713 /// The actual [DmnDiagramElement] this [DmnEdge] is connecting from.
1714 /// MUST be specified when the [DmnEdge] has a source.
1715 pub source_element: Option<String>,
1716 /// The actual [DmnDiagramElement] this [DmnEdge] is connecting to.
1717 /// MUST be specified when the [DmnEdge] has a target.
1718 pub target_element: Option<String>,
1719 /// A reference to a [DmnStyle] defined in the [Dmndi].
1720 pub shared_style: Option<String>,
1721 /// A [DmnStyle] that defines the styling for this element.
1722 pub local_style: Option<DmnStyle>,
1723 /// An optional label when this [DmnElement] has a visible text label.
1724 pub label: Option<DmnLabel>,
1725}
1726
1727//FIXME verify this struct
1728/// tdb
1729#[derive(Debug, Clone)]
1730pub struct Association {}
1731
1732//FIXME verify this struct
1733/// tdb
1734#[derive(Debug, Clone)]
1735pub struct TextAnnotation {}
1736
1737/// [DmnStyle] is used to keep some non-normative visual attributes such as color and font.
1738#[derive(Debug, Clone)]
1739pub struct DmnStyle {
1740 /// A unique identifier for this style so it can be referenced.
1741 /// Only styles defined in the [Dmndi] can be referenced by [DmnDiagramElement] and [DmnDiagram].
1742 pub id: String,
1743 /// The color use to fill the shape.Does not apply to [DmnEdge]. Default is `white`.
1744 pub fill_color: Option<DcColor>,
1745 /// The color use to draw the shape borders. Default is `black`.
1746 pub stroke_color: Option<DcColor>,
1747 /// The color use to draw the label. Default is `black`.
1748 pub font_color: Option<DcColor>,
1749 /// A comma-separated list of Font Name that can be used to display the text. Default is `Arial`.
1750 pub font_family: Option<String>,
1751 /// The size in points of the font to use to display the text. Default is `8` points.
1752 pub font_size: Option<f64>,
1753 /// If the text should be displayed in Italic. Default is `false`.
1754 pub font_italic: Option<bool>,
1755 /// If the text should be displayed in Bold. Default is `false`.
1756 pub font_bold: Option<bool>,
1757 /// If the text should be underlined. Default is `false`.
1758 pub font_underline: Option<bool>,
1759 /// If the text should be stroked through. Default is `false`.
1760 pub font_strike_through: Option<bool>,
1761 /// How text should be positioned horizontally within the Label bounds.
1762 /// Default depends on the [DmnDiagramElement] the label is attached to (see 13.5).
1763 pub label_horizontal_alignment: Option<DcAlignmentKind>,
1764 /// How the text should be positioned vertically inside the Label bounds.
1765 /// Default depends on the [DmnDiagramElement] the label is attached to (see 13.5).
1766 /// Start means `top` and end means `bottom`.
1767 pub label_vertical_alignment: Option<DcAlignmentKind>,
1768}
1769
1770/// Struct represents the depiction of some textual information about a DMN element.
1771#[derive(Debug, Clone)]
1772pub struct DmnLabel {
1773 /// The bounds of the [DmnLabel]. When not specified, the label is positioned
1774 /// at its default position as determined in clause 13.5.
1775 pub bounds: Option<DcBounds>,
1776 /// An optional pretty printed text that MUST be displayed
1777 /// instead of the [DmnElement's](DmnElement) name if it is present.
1778 pub text: Option<String>,
1779 /// A reference to a [DmnStyle] defined in the [Dmndi].
1780 pub shared_style: Option<String>,
1781}
1782
1783/// Defines RGB color.
1784#[derive(Debug, Copy, Clone)]
1785pub struct DcColor {
1786 pub red: u8,
1787 pub green: u8,
1788 pub blue: u8,
1789}
1790
1791impl DcColor {
1792 pub fn white() -> Self {
1793 Self {
1794 red: 0xFF,
1795 green: 0xFF,
1796 blue: 0xFF,
1797 }
1798 }
1799
1800 pub fn black() -> Self {
1801 Self { red: 0x0, green: 0x0, blue: 0x0 }
1802 }
1803}
1804
1805/// Defines point.
1806#[derive(Debug, Copy, Clone)]
1807pub struct DcPoint {
1808 pub x: f64,
1809 pub y: f64,
1810}
1811
1812/// Defines bounds.
1813#[derive(Debug, Copy, Clone)]
1814pub struct DcBounds {
1815 pub x: f64,
1816 pub y: f64,
1817 pub width: f64,
1818 pub height: f64,
1819}
1820
1821/// Defines dimensions.
1822#[derive(Debug, Copy, Clone)]
1823pub struct DcDimension {
1824 pub width: f64,
1825 pub height: f64,
1826}
1827
1828/// Defines the kind of element alignment.
1829#[derive(Debug, Copy, Clone)]
1830pub enum DcAlignmentKind {
1831 /// Left or top.
1832 Start,
1833 /// Right or bottom.
1834 End,
1835 /// Center or middle.
1836 Center,
1837}
1838
1839/// Defines known colors.
1840#[derive(Debug, Copy, Clone)]
1841pub enum DcKnownColor {
1842 Aqua = 0x00FFFF,
1843 Black = 0x000000,
1844 Blue = 0x0000FF,
1845 Fuchsia = 0xFF00FF,
1846 Gray = 0x808080,
1847 Green = 0x008000,
1848 Lime = 0x00FF00,
1849 Maroon = 0x800000,
1850 Navy = 0x000080,
1851 Olive = 0x808000,
1852 Orange = 0xFFA500,
1853 Purple = 0x800080,
1854 Red = 0xFF0000,
1855 Silver = 0xC0C0C0,
1856 Teal = 0x008080,
1857 White = 0xFFFFFF,
1858 Yellow = 0xFFFF00,
1859}