use crate::errors::err_invalid_hit_policy;
use dsntk_common::DsntkError;
use std::fmt;
use std::fmt::Display;
#[derive(Debug, Clone)]
pub struct DecisionTable {
pub information_item_name: Option<String>,
pub input_clauses: Vec<InputClause>,
pub output_clauses: Vec<OutputClause>,
pub annotation_clauses: Vec<AnnotationClause>,
pub rules: Vec<DecisionRule>,
pub hit_policy: HitPolicy,
pub aggregation: Option<BuiltinAggregator>,
pub preferred_orientation: DecisionTableOrientation,
pub output_label: Option<String>,
}
impl DecisionTable {
#[allow(clippy::too_many_arguments)]
pub fn new(
information_item_name: Option<String>,
input_clauses: Vec<InputClause>,
output_clauses: Vec<OutputClause>,
annotation_clauses: Vec<AnnotationClause>,
rules: Vec<DecisionRule>,
hit_policy: HitPolicy,
aggregation: Option<BuiltinAggregator>,
preferred_orientation: DecisionTableOrientation,
output_label: Option<String>,
) -> Self {
Self {
information_item_name,
input_clauses,
output_clauses,
annotation_clauses,
rules,
hit_policy,
aggregation,
preferred_orientation,
output_label,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InputClause {
pub input_expression: String,
pub allowed_input_values: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OutputClause {
pub output_component_name: Option<String>,
pub allowed_output_values: Option<String>,
pub default_output_value: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AnnotationClause {
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DecisionRule {
pub input_entries: Vec<InputEntry>,
pub output_entries: Vec<OutputEntry>,
pub annotation_entries: Vec<AnnotationEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InputEntry {
pub text: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OutputEntry {
pub text: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AnnotationEntry {
pub text: String,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum HitPolicy {
Unique,
Any,
Priority,
First,
Collect(BuiltinAggregator),
OutputOrder,
RuleOrder,
}
impl HitPolicy {
pub fn aggregation(&self) -> Option<BuiltinAggregator> {
match self {
HitPolicy::Collect(aggregation) => Some(*aggregation),
_ => None,
}
}
}
impl Display for HitPolicy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
HitPolicy::Unique => "U",
HitPolicy::Any => "A",
HitPolicy::Priority => "P",
HitPolicy::First => "F",
HitPolicy::RuleOrder => "R",
HitPolicy::OutputOrder => "O",
HitPolicy::Collect(aggregator) => match aggregator {
BuiltinAggregator::List => "C",
BuiltinAggregator::Sum => "C+",
BuiltinAggregator::Count => "C#",
BuiltinAggregator::Min => "C<",
BuiltinAggregator::Max => "C>",
},
}
)
}
}
impl TryFrom<&str> for HitPolicy {
type Error = DsntkError;
fn try_from(value: &str) -> dsntk_common::Result<Self, Self::Error> {
match value.trim() {
"U" => Ok(HitPolicy::Unique),
"A" => Ok(HitPolicy::Any),
"P" => Ok(HitPolicy::Priority),
"F" => Ok(HitPolicy::First),
"R" => Ok(HitPolicy::RuleOrder),
"O" => Ok(HitPolicy::OutputOrder),
"C" => Ok(HitPolicy::Collect(BuiltinAggregator::List)),
"C+" => Ok(HitPolicy::Collect(BuiltinAggregator::Sum)),
"C#" => Ok(HitPolicy::Collect(BuiltinAggregator::Count)),
"C<" => Ok(HitPolicy::Collect(BuiltinAggregator::Min)),
"C>" => Ok(HitPolicy::Collect(BuiltinAggregator::Max)),
other => Err(err_invalid_hit_policy(other)),
}
}
}
impl TryFrom<&String> for HitPolicy {
type Error = DsntkError;
fn try_from(value: &String) -> dsntk_common::Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BuiltinAggregator {
List,
Count,
Sum,
Min,
Max,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum DecisionTableOrientation {
RulesAsRows,
RulesAsColumns,
CrossTable,
}
impl Display for DecisionTableOrientation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
DecisionTableOrientation::RulesAsRows => "rules-as-rows",
DecisionTableOrientation::RulesAsColumns => "rules-as-columns",
DecisionTableOrientation::CrossTable => "cross-table",
}
)
}
}