ebi_objects/attribute_key/
attribute_key.rs1use crate::{Attribute, DataType, Infoable};
2use ebi_arithmetic::anyhow::Result;
3use process_mining::core::event_data::{
4 case_centric::AttributeValue, object_centric::OCELAttributeValue,
5};
6use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator};
7use std::{borrow::Borrow, collections::HashMap};
8
9#[derive(Clone, Debug)]
10pub struct AttributeKey {
11 pub(crate) name2attribute: HashMap<String, Attribute>,
12 pub(crate) attribute2name: Vec<String>,
13 pub(crate) attribute2type: Vec<DataType>,
14}
15
16impl<'a> AttributeKey {
17 pub fn new() -> Self {
18 Self {
19 name2attribute: HashMap::new(),
20 attribute2name: vec![],
21 attribute2type: vec![],
22 }
23 }
24
25 pub fn attribute_to_label(&self, attribute: impl Borrow<Attribute>) -> Option<&String> {
26 self.attribute2name.get(attribute.borrow().id)
27 }
28
29 pub fn label_to_attribute(&self, label: &str) -> Option<Attribute> {
30 self.name2attribute.get(label).copied()
31 }
32
33 pub fn id_to_attribute(&self, attribute_id: usize) -> Attribute {
34 Attribute { id: attribute_id }
35 }
36
37 pub fn attribute_to_id(&self, attribute: impl Borrow<Attribute>) -> usize {
38 attribute.borrow().id
39 }
40
41 pub fn attribute_to_data_type(&self, attribute: impl Borrow<Attribute>) -> Option<&DataType> {
42 self.attribute2type.get(attribute.borrow().id)
43 }
44
45 pub fn set_label(&mut self, attribute: impl Borrow<Attribute>, label: &str) {
46 if let Some(old_label) = self.attribute2name.get(attribute.borrow().id) {
47 let old_label = old_label.to_string();
48 self.attribute2name[attribute.borrow().id] = label.to_string();
49 self.name2attribute.remove(&old_label);
50 self.name2attribute
51 .insert(label.to_string(), attribute.borrow().clone());
52 }
53 }
54
55 #[cfg(test)]
56 pub fn add_categorical_attribute(&mut self, label: &str) -> Attribute {
57 let next_index = self.name2attribute.len();
58 match self.name2attribute.get(label) {
59 Some(attribute) => *attribute,
60 None => {
61 let result = Attribute { id: next_index };
62 self.attribute2name.push(label.to_string());
63 self.name2attribute.insert(label.to_string(), result);
64 self.attribute2type.push(DataType::Categorical);
65 return result;
66 }
67 }
68 }
69
70 pub fn process_attribute_column(
72 &mut self,
73 attribute_id: usize,
74 attribute_value: &str,
75 ) -> Attribute {
76 if attribute_id == self.name2attribute.len() {
77 let id = self.attribute2name.len();
78 self.attribute2name.push(id.to_string());
79 self.name2attribute.insert(id.to_string(), Attribute { id });
80 self.attribute2type
81 .push(DataType::init(&AttributeValue::String(
82 attribute_value.to_string(),
83 )));
84 self.id_to_attribute(id)
85 } else {
86 self.attribute2type[attribute_id]
87 .update(&AttributeValue::String(attribute_value.to_string()));
88 self.id_to_attribute(attribute_id)
89 }
90 }
91
92 pub fn process_attribute_value(
93 &mut self,
94 attribute_name: &str,
95 attribute_value: &AttributeValue,
96 ) -> Attribute {
97 let next_index = self.name2attribute.len();
98 match self.name2attribute.get(attribute_name) {
99 Some(index) => {
100 self.attribute2type[index.id].update(attribute_value);
101 return *index;
102 }
103 None => {
104 let result = Attribute { id: next_index };
105 self.attribute2name.push(attribute_name.to_string());
106 self.name2attribute
107 .insert(attribute_name.to_string(), result);
108 self.attribute2type.push(DataType::init(&attribute_value));
109 return result;
110 }
111 }
112 }
113
114 pub fn ocel_attribute_value2attribute_value(ocel_value: OCELAttributeValue) -> AttributeValue {
115 match ocel_value {
116 OCELAttributeValue::Time(d) => AttributeValue::Date(d),
117 OCELAttributeValue::Integer(i) => AttributeValue::Int(i),
118 OCELAttributeValue::Float(f) => AttributeValue::Float(f),
119 OCELAttributeValue::Boolean(b) => AttributeValue::Boolean(b),
120 OCELAttributeValue::String(s) => AttributeValue::String(s),
121 OCELAttributeValue::Null => AttributeValue::None(),
122 }
123 }
124
125 pub fn len(&self) -> usize {
126 self.attribute2name.len()
127 }
128}
129
130impl Infoable for AttributeKey {
131 fn info(&self, f: &mut impl std::io::Write) -> Result<()> {
132 let mut tuples = self
134 .attribute2name
135 .iter()
136 .zip(self.attribute2type.iter())
137 .collect::<Vec<_>>();
138 tuples.sort_by(|a, b| a.0.cmp(b.0));
139
140 for (label, typee) in tuples {
141 writeln!(f, "\t{}\t{}", label, typee)?;
142 }
143
144 Ok(write!(f, "")?)
145 }
146}
147
148impl<'a> IntoParallelIterator for &'a AttributeKey {
149 type Iter = rayon::iter::Zip<rayon::vec::IntoIter<Attribute>, rayon::slice::Iter<'a, DataType>>;
150 type Item = (Attribute, &'a DataType);
151
152 fn into_par_iter(self) -> Self::Iter {
153 let x = (0..self.len())
154 .map(|id| self.id_to_attribute(id))
155 .collect::<Vec<_>>();
156
157 x.into_par_iter().zip(self.attribute2type.par_iter())
158 }
159}