Merge pull request #1110 from matthiasbeyer/libimagcontact/init
Libimagcontact/init
This commit is contained in:
commit
6efd0a9450
10 changed files with 470 additions and 0 deletions
|
@ -21,6 +21,7 @@ members = [
|
|||
"lib/core/libimagrt",
|
||||
"lib/core/libimagstore",
|
||||
"lib/domain/libimagbookmark",
|
||||
"lib/domain/libimagcontact",
|
||||
"lib/domain/libimagdiary",
|
||||
"lib/domain/libimagmail",
|
||||
"lib/domain/libimagnotes",
|
||||
|
|
|
@ -1,2 +1,49 @@
|
|||
## libimagcontacts
|
||||
|
||||
The contact library basically only creates references to the actual icalendar
|
||||
and vcard files, though it also can parse (via the `vobject` crate) the
|
||||
information and return it from an entry directly.
|
||||
|
||||
The architecture of indirections is as follows:
|
||||
|
||||
```{.numberLines}
|
||||
|
||||
+--------------------------------+
|
||||
| |
|
||||
| Store, as ContactStore |
|
||||
| |
|
||||
+----------------+---------------+
|
||||
|
|
||||
| Provides access to
|
||||
|
|
||||
+----------------v---------------+
|
||||
| |
|
||||
| (FileLock)Entry as Contact |
|
||||
| |
|
||||
| which is actually a: |
|
||||
| |
|
||||
| (FileLock)Entry as Ref |
|
||||
| |
|
||||
+----------------+---------------+
|
||||
|
|
||||
| refers to
|
||||
|
|
||||
+----------------v---------------+
|
||||
| |
|
||||
| vcard file (outside store) |
|
||||
| |
|
||||
+----------------+---------------+
|
||||
|
|
||||
| contains
|
||||
|
|
||||
+----------------v---------------+
|
||||
| |
|
||||
| vcard data |
|
||||
| |
|
||||
+--------------------------------+
|
||||
|
||||
```
|
||||
|
||||
As the library is build upon `libimagentryref`, it does not create a new
|
||||
subcollection in the store `/contacts`, but uses the infrastructure of
|
||||
`libimagentryref` which automatically puts all references in `/ref`.
|
||||
|
|
26
lib/domain/libimagcontact/Cargo.toml
Normal file
26
lib/domain/libimagcontact/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "libimagcontact"
|
||||
version = "0.5.0"
|
||||
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
|
||||
|
||||
description = "Library for the imag core distribution"
|
||||
|
||||
keywords = ["imag", "PIM", "personal", "information", "management"]
|
||||
readme = "../../../README.md"
|
||||
license = "LGPL-2.1"
|
||||
|
||||
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
|
||||
repository = "https://github.com/matthiasbeyer/imag"
|
||||
homepage = "http://imag-pim.org"
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.11"
|
||||
log = "0.3"
|
||||
toml = "0.4"
|
||||
toml-query = "0.4"
|
||||
vobject = { git = 'https://github.com/matthiasbeyer/rust-vobject', branch = "next" }
|
||||
|
||||
libimagstore = { version = "0.5.0", path = "../../../lib/core/libimagstore" }
|
||||
libimagerror = { version = "0.5.0", path = "../../../lib/core/libimagerror" }
|
||||
libimagentryref = { version = "0.5.0", path = "../../../lib/entry/libimagentryref/" }
|
||||
|
1
lib/domain/libimagcontact/README.md
Symbolic link
1
lib/domain/libimagcontact/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../doc/src/05100-lib-contacts.md
|
90
lib/domain/libimagcontact/src/contact.rs
Normal file
90
lib/domain/libimagcontact/src/contact.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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::ops::Deref;
|
||||
|
||||
use vobject::Component;
|
||||
use toml::Value;
|
||||
use toml_query::read::TomlValueReadExt;
|
||||
|
||||
use libimagstore::store::Entry;
|
||||
use libimagentryref::reference::Ref;
|
||||
|
||||
use error::ContactError as CE;
|
||||
use error::ContactErrorKind as CEK;
|
||||
use error::Result;
|
||||
use util;
|
||||
|
||||
/// Trait to be implemented on ::libimagstore::store::Entry
|
||||
///
|
||||
/// Based on the functionality from libimagentryref, for fetching the Ical data from disk
|
||||
pub trait Contact : Ref {
|
||||
|
||||
fn is_contact(&self) -> Result<bool>;
|
||||
|
||||
// getting data
|
||||
|
||||
fn get_contact_data(&self) -> Result<ContactData>;
|
||||
|
||||
// More convenience functionality may follow
|
||||
|
||||
}
|
||||
|
||||
impl Contact for Entry {
|
||||
|
||||
fn is_contact(&self) -> Result<bool> {
|
||||
let location = "contact.marker";
|
||||
match self.get_header().read(location)? {
|
||||
Some(&Value::Boolean(b)) => Ok(b),
|
||||
Some(_) => Err(CE::from_kind(CEK::HeaderTypeError("boolean", location))),
|
||||
None => Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_contact_data(&self) -> Result<ContactData> {
|
||||
let component = self
|
||||
.fs_file()
|
||||
.map_err(From::from)
|
||||
.and_then(util::read_to_string)
|
||||
.and_then(util::parse)?;
|
||||
|
||||
Ok(ContactData(component))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct ContactData(Component);
|
||||
|
||||
impl ContactData {
|
||||
|
||||
pub fn into_inner(self) -> Component {
|
||||
self.0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Deref for ContactData {
|
||||
type Target = Component;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
52
lib/domain/libimagcontact/src/error.rs
Normal file
52
lib/domain/libimagcontact/src/error.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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 libimagstore::storeid::StoreId;
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
ContactError, ContactErrorKind, ResultExt, Result;
|
||||
}
|
||||
|
||||
links {
|
||||
StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind);
|
||||
RefError(::libimagentryref::error::RefError, ::libimagentryref::error::RefErrorKind);
|
||||
VObjectError(::vobject::error::VObjectError, ::vobject::error::VObjectErrorKind);
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Io(::std::io::Error);
|
||||
TomlQueryError(::toml_query::error::Error);
|
||||
}
|
||||
|
||||
errors {
|
||||
|
||||
HeaderTypeError(ty: &'static str, loc: &'static str) {
|
||||
description("Type error in header")
|
||||
display("Type error in header, expected {} at '{}', found other type", ty, loc)
|
||||
}
|
||||
|
||||
EntryNotFound(sid: StoreId) {
|
||||
description("Entry not found with StoreId")
|
||||
display("Entry {:?} not found", sid)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
69
lib/domain/libimagcontact/src/iter.rs
Normal file
69
lib/domain/libimagcontact/src/iter.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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 libimagstore::storeid::StoreIdIterator;
|
||||
use libimagstore::store::Store;
|
||||
use libimagstore::store::FileLockEntry;
|
||||
|
||||
use contact::Contact;
|
||||
use error::ContactError as CE;
|
||||
use error::ContactErrorKind as CEK;
|
||||
use error::Result;
|
||||
|
||||
pub struct ContactIter<'a>(StoreIdIterator, &'a Store);
|
||||
|
||||
/// Iterator over contacts
|
||||
///
|
||||
/// As the libimagcontact works with libimagentryref in the backend, we must hold a reference to the
|
||||
/// Store here as well, so we can check whether a fetched StoreId actually points to a contact
|
||||
/// reference or not.
|
||||
///
|
||||
/// So, the Iterator `Store::get()`s the object pointed to by the StoreId and returns it if
|
||||
/// everything worked.
|
||||
impl<'a> ContactIter<'a> {
|
||||
|
||||
pub fn new(sii: StoreIdIterator, store: &'a Store) -> ContactIter<'a> {
|
||||
ContactIter(sii, store)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ContactIter<'a> {
|
||||
type Item = Result<FileLockEntry<'a>>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.0.next() {
|
||||
None => return None,
|
||||
Some(sid) => match self.1.get(sid.clone()).map_err(From::from) {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Ok(None) => return Some(Err(CE::from_kind(CEK::EntryNotFound(sid)))),
|
||||
Ok(Some(entry)) => match entry.is_contact().map_err(From::from) {
|
||||
Ok(true) => return Some(Ok(entry)),
|
||||
Ok(false) => continue,
|
||||
Err(e) => return Some(Err(e)),
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
53
lib/domain/libimagcontact/src/lib.rs
Normal file
53
lib/domain/libimagcontact/src/lib.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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
|
||||
//
|
||||
|
||||
#![deny(
|
||||
dead_code,
|
||||
non_camel_case_types,
|
||||
non_snake_case,
|
||||
path_statements,
|
||||
trivial_numeric_casts,
|
||||
unstable_features,
|
||||
unused_allocation,
|
||||
unused_import_braces,
|
||||
unused_imports,
|
||||
unused_must_use,
|
||||
unused_mut,
|
||||
unused_qualifications,
|
||||
while_true,
|
||||
)]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate error_chain;
|
||||
extern crate vobject;
|
||||
extern crate toml;
|
||||
extern crate toml_query;
|
||||
|
||||
#[macro_use] extern crate libimagstore;
|
||||
extern crate libimagerror;
|
||||
extern crate libimagentryref;
|
||||
|
||||
module_entry_path_mod!("contact");
|
||||
|
||||
pub mod contact;
|
||||
pub mod error;
|
||||
pub mod iter;
|
||||
pub mod store;
|
||||
mod util;
|
||||
|
86
lib/domain/libimagcontact/src/store.rs
Normal file
86
lib/domain/libimagcontact/src/store.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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::PathBuf;
|
||||
|
||||
use vobject::parse_component;
|
||||
use toml::Value;
|
||||
use toml_query::insert::TomlValueInsertExt;
|
||||
|
||||
use libimagstore::store::Store;
|
||||
use libimagstore::store::FileLockEntry;
|
||||
use libimagstore::storeid::StoreIdIterator;
|
||||
use libimagentryref::refstore::RefStore;
|
||||
use libimagentryref::flags::RefFlags;
|
||||
|
||||
use error::Result;
|
||||
use util;
|
||||
|
||||
pub trait ContactStore<'a> : RefStore {
|
||||
|
||||
// creating
|
||||
|
||||
fn create_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>>;
|
||||
|
||||
/// Create contact ref from buffer
|
||||
///
|
||||
/// Needs the `p` argument as we're finally creating a reference by path, the buffer is only for
|
||||
/// collecting metadata.
|
||||
fn create_from_buf(&'a self, p: &PathBuf, buf: &String) -> Result<FileLockEntry<'a>>;
|
||||
|
||||
// getting
|
||||
|
||||
fn all_contacts(&'a self) -> Result<StoreIdIterator>;
|
||||
}
|
||||
|
||||
/// The extension for the Store to work with contacts
|
||||
///
|
||||
/// The contact functionality is implemented by using the `libimagentryref` library, so basically
|
||||
/// we only reference vcard files from outside the store.
|
||||
///
|
||||
/// Because of this, we do not have an own store collection `/contacts` or something like that, but
|
||||
/// must stress the `libimagentryref` API for everything.
|
||||
impl<'a> ContactStore<'a> for Store {
|
||||
|
||||
fn create_from_path(&'a self, p: &PathBuf) -> Result<FileLockEntry<'a>> {
|
||||
util::read_to_string(p).and_then(|buf| self.create_from_buf(p, &buf))
|
||||
}
|
||||
|
||||
/// Create contact ref from buffer
|
||||
fn create_from_buf(&'a self, p: &PathBuf, buf: &String) -> Result<FileLockEntry<'a>> {
|
||||
let component = parse_component(&buf)?;
|
||||
debug!("Parsed: {:?}", component);
|
||||
|
||||
let flags = RefFlags::default().with_content_hashing(true).with_permission_tracking(false);
|
||||
RefStore::create(self, p.clone(), flags)
|
||||
.map_err(From::from)
|
||||
.and_then(|mut entry| {
|
||||
entry.get_header_mut()
|
||||
.insert("contact.marker", Value::Boolean(true))
|
||||
.map_err(From::from)
|
||||
.map(|_| entry)
|
||||
})
|
||||
}
|
||||
|
||||
fn all_contacts(&'a self) -> Result<StoreIdIterator> {
|
||||
self.all_references().map_err(From::from)
|
||||
}
|
||||
|
||||
}
|
||||
|
45
lib/domain/libimagcontact/src/util.rs
Normal file
45
lib/domain/libimagcontact/src/util.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// imag - the personal information management suite for the commandline
|
||||
// Copyright (C) 2015, 2016 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 std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use error::Result;
|
||||
|
||||
use vobject::Component;
|
||||
|
||||
pub fn read_to_string<A: AsRef<Path> + Debug>(pb: A) -> Result<String> {
|
||||
let mut cont = String::new();
|
||||
|
||||
let mut file = File::open(pb.as_ref())?;
|
||||
let bytes = file.read_to_string(&mut cont)?;
|
||||
|
||||
debug!("Read {} bytes from {:?}", bytes, pb);
|
||||
|
||||
Ok(cont)
|
||||
}
|
||||
|
||||
/// Helper for chaining results nicely
|
||||
pub fn parse(buf: String) -> Result<Component> {
|
||||
use vobject::parse_component;
|
||||
parse_component(&buf).map_err(From::from)
|
||||
}
|
||||
|
Loading…
Reference in a new issue