use std::collections::BTreeSet;
use chrono::{DateTime, Utc};
use crate::model::{Event, Ocel};
impl Ocel {
#[must_use]
pub fn filter_events<F>(&self, pred: F) -> Ocel
where
F: Fn(&Event) -> bool,
{
let kept_events: Vec<&Event> = self.events.iter().filter(|e| pred(e)).collect();
let kept_objects: BTreeSet<&str> = kept_events
.iter()
.flat_map(|e| e.relationships.iter().map(|r| r.object_id.as_str()))
.collect();
self.subset(|e| pred(e), |id| kept_objects.contains(id), KeepEvents::All)
}
#[must_use]
pub fn filter_event_types(&self, names: &[&str]) -> Ocel {
self.filter_events(|e| names.contains(&e.event_type.as_str()))
}
#[must_use]
pub fn filter_time_range(&self, from: DateTime<Utc>, to: DateTime<Utc>) -> Ocel {
self.filter_events(|e| e.time >= from && e.time <= to)
}
#[must_use]
pub fn filter_object_types(&self, names: &[&str]) -> Ocel {
let kept_objects: BTreeSet<&str> = self
.objects
.iter()
.filter(|o| names.contains(&o.object_type.as_str()))
.map(|o| o.id.as_str())
.collect();
self.subset(
|_| true,
|id| kept_objects.contains(id),
KeepEvents::RelatedToKeptObjects,
)
}
pub(crate) fn subset<E, O>(&self, keep_event: E, keep_object: O, mode: KeepEvents) -> Ocel
where
E: Fn(&Event) -> bool,
O: Fn(&str) -> bool,
{
let events = self
.events
.iter()
.filter(|e| keep_event(e))
.map(|e| {
let mut event = e.clone();
event
.relationships
.retain(|r| keep_object(r.object_id.as_str()));
event
})
.filter(|e| match mode {
KeepEvents::All => true,
KeepEvents::RelatedToKeptObjects => !e.relationships.is_empty(),
})
.collect();
let objects = self
.objects
.iter()
.filter(|o| keep_object(o.id.as_str()))
.map(|o| {
let mut object = o.clone();
object
.relationships
.retain(|r| keep_object(r.object_id.as_str()));
object
})
.collect();
Ocel {
event_types: self.event_types.clone(),
object_types: self.object_types.clone(),
events,
objects,
}
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum KeepEvents {
All,
RelatedToKeptObjects,
}