libimagentryannotation/
annotateable.rs1use toml::Value;
21use uuid::Uuid;
22
23use libimagstore::store::Entry;
24use libimagstore::store::FileLockEntry;
25use libimagstore::store::Store;
26use libimagstore::storeid::StoreIdIterator;
27use libimagentrylink::linkable::Linkable;
28use libimagentryutil::isa::Is;
29use libimagentryutil::isa::IsKindHeaderPathProvider;
30
31use toml_query::insert::TomlValueInsertExt;
32
33use failure::Fallible as Result;
34use failure::ResultExt;
35use failure::Error;
36use failure::err_msg;
37
38pub trait Annotateable {
39 fn annotate<'a>(&mut self, store: &'a Store) -> Result<FileLockEntry<'a>>;
40 fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>>;
41 fn annotations(&self) -> Result<StoreIdIterator>;
42 fn is_annotation(&self) -> Result<bool>;
43}
44
45provide_kindflag_path!(IsAnnotation, "annotation.is_annotation");
46
47impl Annotateable for Entry {
48
49 fn annotate<'a>(&mut self, store: &'a Store) -> Result<FileLockEntry<'a>> {
51 let ann_name = Uuid::new_v4().to_hyphenated().to_string();
52 debug!("Creating annotation with name = {}", ann_name);
53
54 store.retrieve(crate::module_path::new_id(ann_name.clone())?)
55 .and_then(|mut anno| {
56 {
57 anno.set_isflag::<IsAnnotation>()?;
58 let _ = anno
59 .get_header_mut()
60 .insert("annotation.name", Value::String(ann_name))?;
61 }
62 Ok(anno)
63 })
64 .and_then(|mut anno| {
65 anno.add_link(self)
66 .context(err_msg("Linking error"))
67 .map_err(Error::from)
68 .map(|_| anno)
69 })
70 }
71
72 fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>> {
76 if let Some(mut annotation) = store.get(crate::module_path::new_id(ann_name)?)? {
77 self.remove_link(&mut annotation)?;
78 Ok(Some(annotation))
79 } else {
80 Err(format_err!("Annotation '{}' does not exist", ann_name)).map_err(Error::from)
82 }
83 }
84
85 fn annotations(&self) -> Result<StoreIdIterator> {
87 self.links()
88 .map(|it| {
89 it.filter(|link| link.get_store_id().is_in_collection(&["annotation"]))
90 .map(|link| Ok(link.get_store_id().clone()))
91 })
92 .map(Box::new)
93 .map(|inner| StoreIdIterator::new(inner))
94 }
95
96 fn is_annotation(&self) -> Result<bool> {
97 self.is::<IsAnnotation>()
98 }
99
100}
101