imag/lib/domain/libimagcalendar/src/store.rs

120 lines
4.2 KiB
Rust
Raw Normal View History

//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::path::Path;
use failure::Fallible as Result;
use toml::Value;
use toml_query::insert::TomlValueInsertExt;
use vobject::ICalendar;
use libimagentryutil::isa::Is;
use libimagentryref::reference::Config;
use libimagentryref::reference::MutRef;
use libimagentryref::hasher::default::DefaultHasher;
use libimagentryref::reference::RefFassade;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::iter::Entries;
use crate::event::IsEvent;
pub trait EventStore<'a> {
/// Imports events from a filepath
///
/// # Note
///
/// Because one icalendar file can theoretically hold several events, this function returns a
/// list of entries.
///
/// # Parameters
///
/// This function is basically a wrapper around `libimagentryref::reference::RefMut::make_ref()`
/// which also does some parsing and Store::create() ing entry objects.
///
/// Because of the former function, this requires some parameters which are documented in the
/// documentation of this function:
///
/// libimagentryref::reference::RefMut::make_ref()
///
/// Normally, `force` should be set to `false`.
///
fn import_from_path<P, Coll>(&'a self, p: P, basepath_name: Coll, refconfig: &Config, force: bool)
-> Result<Vec<Result<FileLockEntry<'a>>>>
where P: AsRef<Path>,
Coll: AsRef<str>;
fn get_event_by_uid<ID>(&'a self, id: ID) -> Result<Option<FileLockEntry<'a>>>
where ID: AsRef<str>;
/// Get all events
fn all_events(&'a self) -> Result<Entries<'a>>;
}
impl<'a> EventStore<'a> for Store {
fn import_from_path<P, Coll>(&'a self, p: P, basepath_name: Coll, refconfig: &Config, force: bool)
-> Result<Vec<Result<FileLockEntry<'a>>>>
where P: AsRef<Path>,
Coll: AsRef<str>
{
let text = std::fs::read_to_string(p.as_ref())?;
Ok(ICalendar::build(&text)?
.events()
.filter_map(|rresult| match rresult {
Ok(event) => Some(event),
Err(component) => {
debug!("Ignoring non-event Component in {}: {}", p.as_ref().display(), component.name);
None
}
})
.map(|event| {
let uid = event.uid().ok_or_else(|| {
format_err!("Event in {} has no UID, but icalendar events must have one.", p.as_ref().display())
})?;
let sid = crate::module_path::new_id(uid.raw())?;
let uid_header = Value::String(uid.into_raw());
let mut entry = self.create(sid)?;
let _ = entry
.as_ref_with_hasher_mut::<DefaultHasher>()
.make_ref(p.as_ref(), basepath_name.as_ref(), refconfig, force)?;
let _ = entry.get_header_mut().insert("calendar.event.uid", uid_header)?;
let _ = entry.set_isflag::<IsEvent>()?;
Ok(entry)
})
.collect())
}
fn get_event_by_uid<ID>(&'a self, id: ID) -> Result<Option<FileLockEntry<'a>>>
where ID: AsRef<str>
{
self.get(crate::module_path::new_id(id.as_ref())?)
}
/// Get all events
///
/// Uses Store::entries(), so there might be false positives.
fn all_events(&'a self) -> Result<Entries<'a>> {
self.entries().and_then(|es| es.in_collection("calendar"))
}
}