1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Graph operation modules change the imported corpus data.
pub mod align;
pub mod check;
pub mod chunker;
pub mod collapse;
pub mod diff;
pub mod divide;
pub mod edit;
pub mod enumerate;
pub mod filter;
pub mod link;
pub mod map;
pub mod no_op;
pub mod re;
pub mod sleep;
pub mod span;
pub mod split;
pub mod time;
pub mod visualize;
use crate::{
StepID,
workflow::{StatusMessage, StatusSender},
};
use graphannis::AnnotationGraph;
use std::path::Path;
/// A a manipulator is a module that changes an annotation graph.
/// Manipulators are applied in sequence to the same annotation graph instance.
pub trait Manipulator: Sync {
/// Manipulates an annotation graph.
///
/// # Arguments
///
/// * `graph` - A mutable reference to the annotation graph to manipulate.
/// * `properties` - A map of configuration properties as given in the workflow description.
/// * `step_id` - The ID of the step.
/// * `tx` - If supported by the caller, this is a sender object that allows to send [status updates](../workflow/enum.StatusMessage.html) (like information messages, warnings and module progress) to the calling entity.
///
fn manipulate_corpus(
&self,
graph: &mut AnnotationGraph,
workflow_directory: &Path,
step_id: StepID,
tx: Option<StatusSender>,
) -> Result<(), Box<dyn std::error::Error>>;
/// If the manipulator queries the graph using AQL, the search requires graph statistics.
fn requires_statistics(&self) -> bool;
/// This step needs to be run before manipulation to make sure the graph has updated statistics,
/// given the module indicates the requirement via [requires_statistics()].
fn validate_graph(
&self, // this is only because Rust doesn't allow associated functions for trait objects while being dyn compatible
graph: &mut AnnotationGraph,
step_id: StepID,
tx: Option<StatusSender>,
) -> Result<(), anyhow::Error> {
if self.requires_statistics() && graph.global_statistics.is_none() {
if let Some(sender) = tx {
sender.send(StatusMessage::Info(format!(
"Computing graph statistics for step {} ...",
step_id.module_name
)))?;
}
graph.calculate_all_statistics()?;
}
Ok(())
}
}