From f0969db47cef7253d3fcd83c210f0b1687c4a633 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 26 Apr 2018 12:04:18 +0200 Subject: [PATCH] Rewrite This patch rewrites the whole libimagcategory and brings it to a nice standard (the code before was rather messy). Now, categories are represented by an entry in the store and all entries which have this category are linked to that entry. --- lib/entry/libimagentrycategory/Cargo.toml | 14 +++--- .../libimagentrycategory/src/category.rs | 29 +++++++++--- lib/entry/libimagentrycategory/src/entry.rs | 47 +++++++------------ lib/entry/libimagentrycategory/src/error.rs | 7 +++ lib/entry/libimagentrycategory/src/iter.rs | 45 ++++++++++++++++-- lib/entry/libimagentrycategory/src/lib.rs | 8 ++-- lib/entry/libimagentrycategory/src/store.rs | 14 ++++-- 7 files changed, 110 insertions(+), 54 deletions(-) diff --git a/lib/entry/libimagentrycategory/Cargo.toml b/lib/entry/libimagentrycategory/Cargo.toml index 472d1b1e..70c6ee02 100644 --- a/lib/entry/libimagentrycategory/Cargo.toml +++ b/lib/entry/libimagentrycategory/Cargo.toml @@ -20,14 +20,16 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" } maintenance = { status = "actively-developed" } [dependencies] -log = "0.4.0" -toml = "0.4" -toml-query = "0.6" -is-match = "0.1" +log = "0.4.0" +toml = "0.4" +toml-query = "0.6" error-chain = "0.11" -libimagerror = { version = "0.8.0", path = "../../../lib/core/libimagerror" } -libimagstore = { version = "0.8.0", path = "../../../lib/core/libimagstore" } +libimagerror = { version = "0.8.0", path = "../../../lib/core/libimagerror" } +libimagstore = { version = "0.8.0", path = "../../../lib/core/libimagstore" } +libimagutil = { version = "0.8.0", path = "../../../lib/etc/libimagutil" } +libimagentryutil = { version = "0.8.0", path = "../../../lib/entry/libimagentryutil" } +libimagentrylink = { version = "0.8.0", path = "../../../lib/entry/libimagentrylink" } [dev-dependencies] env_logger = "0.5" diff --git a/lib/entry/libimagentrycategory/src/category.rs b/lib/entry/libimagentrycategory/src/category.rs index 9fdb397b..fab8715f 100644 --- a/lib/entry/libimagentrycategory/src/category.rs +++ b/lib/entry/libimagentrycategory/src/category.rs @@ -19,16 +19,25 @@ use libimagentryutil::isa::Is; use libimagentryutil::isa::IsKindHeaderPathProvider; +use libimagstore::store::Entry; +use libimagstore::store::Store; +use libimagstore::storeid::StoreIdIterator; +use libimagentrylink::internal::InternalLinker; +use toml_query::read::TomlValueReadTypeExt; + +use error::Result; use error::CategoryError as CE; +use error::CategoryErrorKind as CEK; use store::CATEGORY_REGISTER_NAME_FIELD_PATH; +use iter::CategoryEntryIterator; provide_kindflag_path!(pub IsCategory, "category.is_category"); pub trait Category { - fn is_category(&self) -> Result; - fn get_name(&self) -> Result; - fn get_entries(&self, store: &Store) -> Result; + fn is_category(&self) -> Result; + fn get_name(&self) -> Result; + fn get_entries<'a>(&self, store: &'a Store) -> Result>; } impl Category for Entry { @@ -37,11 +46,19 @@ impl Category for Entry { } fn get_name(&self) -> Result { - self.get_header().read_string(CATEGORY_REGISTER_NAME_FIELD_PATH).map_err(CE::from) + trace!("Getting category name of '{:?}'", self.get_location()); + self.get_header() + .read_string(CATEGORY_REGISTER_NAME_FIELD_PATH) + .map_err(CE::from)? + .ok_or_else(|| CE::from_kind(CEK::CategoryNameMissing)) } - fn get_entries(&self, store: &Store) -> Result { - unimplemented!() + fn get_entries<'a>(&self, store: &'a Store) -> Result> { + trace!("Getting linked entries for category '{:?}'", self.get_location()); + let sit = self.get_internal_links()?.map(|l| l.get_store_id().clone()); + let sit = StoreIdIterator::new(Box::new(sit)); + let name = self.get_name()?; + Ok(CategoryEntryIterator::new(store, sit, name)) } } diff --git a/lib/entry/libimagentrycategory/src/entry.rs b/lib/entry/libimagentrycategory/src/entry.rs index a9abe76c..c6f82e04 100644 --- a/lib/entry/libimagentrycategory/src/entry.rs +++ b/lib/entry/libimagentrycategory/src/entry.rs @@ -23,37 +23,21 @@ use toml_query::read::TomlValueReadTypeExt; use toml::Value; use libimagstore::store::Entry; +use libimagentrylink::internal::InternalLinker; use error::CategoryErrorKind as CEK; use error::CategoryError as CE; use error::ResultExt; use error::Result; -use register::CategoryRegister; - -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct Category(String); - -impl From for Category { - - fn from(s: String) -> Category { - Category(s) - } - -} - -impl Into for Category { - fn into(self) -> String { - self.0 - } -} +use store::CategoryStore; pub trait EntryCategory { - fn set_category(&mut self, s: Category) -> Result<()>; + fn set_category(&mut self, s: &str) -> Result<()>; - fn set_category_checked(&mut self, register: &CategoryRegister, s: Category) -> Result<()>; + fn set_category_checked(&mut self, register: &CategoryStore, s: &str) -> Result<()>; - fn get_category(&self) -> Result>; + fn get_category(&self) -> Result; fn has_category(&self) -> Result; @@ -61,9 +45,10 @@ pub trait EntryCategory { impl EntryCategory for Entry { - fn set_category(&mut self, s: Category) -> Result<()> { + fn set_category(&mut self, s: &str) -> Result<()> { + trace!("Setting category '{}' UNCHECKED", s); self.get_header_mut() - .insert(&String::from("category.value"), Value::String(s.into())) + .insert(&String::from("category.value"), Value::String(s.to_string())) .chain_err(|| CEK::HeaderWriteError) .map(|_| ()) } @@ -71,10 +56,10 @@ impl EntryCategory for Entry { /// Check whether a category exists before setting it. /// /// This function should be used by default over EntryCategory::set_category()! - fn set_category_checked(&mut self, register: &CategoryRegister, s: Category) -> Result<()> { - let c_str = s.clone().into(); + fn set_category_checked(&mut self, register: &CategoryStore, s: &str) -> Result<()> { + trace!("Setting category '{}' checked", s); let mut category = register - .get_category_by_name(&c_str)? + .get_category_by_name(s)? .ok_or_else(|| CE::from_kind(CEK::CategoryDoesNotExist))?; let _ = self.set_category(s)?; @@ -83,15 +68,15 @@ impl EntryCategory for Entry { Ok(()) } - fn get_category(&self) -> Result> { + fn get_category(&self) -> Result { + trace!("Getting category from '{}'", self.get_location()); self.get_header() - .read_string("category.value") - .chain_err(|| CEK::HeaderReadError) - .and_then(|o| o.map(Category::from).ok_or(CE::from_kind(CEK::TypeError))) - .map(Some) + .read_string("category.value")? + .ok_or_else(|| CE::from_kind(CEK::CategoryNameMissing)) } fn has_category(&self) -> Result { + trace!("Has category? '{}'", self.get_location()); self.get_header().read("category.value") .chain_err(|| CEK::HeaderReadError) .map(|x| x.is_some()) diff --git a/lib/entry/libimagentrycategory/src/error.rs b/lib/entry/libimagentrycategory/src/error.rs index 9cf446e6..f9b90ff3 100644 --- a/lib/entry/libimagentrycategory/src/error.rs +++ b/lib/entry/libimagentrycategory/src/error.rs @@ -24,6 +24,8 @@ error_chain! { links { StoreError(::libimagstore::error::StoreError, ::libimagstore::error::StoreErrorKind); + LinkError(::libimagentrylink::error::LinkError, ::libimagentrylink::error::LinkErrorKind); + EntryUtilError(::libimagentryutil::error::EntryUtilError, ::libimagentryutil::error::EntryUtilErrorKind); } foreign_links { @@ -65,6 +67,11 @@ error_chain! { description("Type Error") display("Type Error") } + + CategoryNameMissing { + description("Category name is missing") + display("Category name is missing") + } } } diff --git a/lib/entry/libimagentrycategory/src/iter.rs b/lib/entry/libimagentrycategory/src/iter.rs index 7896bcbd..a835b82a 100644 --- a/lib/entry/libimagentrycategory/src/iter.rs +++ b/lib/entry/libimagentrycategory/src/iter.rs @@ -19,11 +19,16 @@ use libimagstore::storeid::StoreIdIterator; use libimagstore::store::Store; +use libimagstore::store::FileLockEntry; + +use toml_query::read::TomlValueReadTypeExt; use error::Result; use error::CategoryError as CE; use error::CategoryErrorKind as CEK; use store::CATEGORY_REGISTER_NAME_FIELD_PATH; +use entry::EntryCategory; +use error::ResultExt; /// Iterator for Category names /// @@ -41,14 +46,14 @@ pub struct CategoryNameIter<'a>(&'a Store, StoreIdIterator); impl<'a> CategoryNameIter<'a> { - fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { + pub(crate) fn new(store: &'a Store, sidit: StoreIdIterator) -> CategoryNameIter<'a> { CategoryNameIter(store, sidit) } } impl<'a> Iterator for CategoryNameIter<'a> { - type Item = Result; + type Item = Result; fn next(&mut self) -> Option { // TODO: Optimize me with lazy_static @@ -63,7 +68,6 @@ impl<'a> Iterator for CategoryNameIter<'a> { .get_header() .read_string(query) .chain_err(|| CEK::HeaderReadError)? - .map(Category::from) .ok_or_else(|| CE::from_kind(CEK::StoreReadError)) }; @@ -75,3 +79,38 @@ impl<'a> Iterator for CategoryNameIter<'a> { } } +pub struct CategoryEntryIterator<'a>(&'a Store, StoreIdIterator, String); + +impl<'a> CategoryEntryIterator<'a> { + pub(crate) fn new(store: &'a Store, sit: StoreIdIterator, name: String) -> Self { + CategoryEntryIterator(store, sit, name) + } +} + +impl<'a> Iterator for CategoryEntryIterator<'a> { + type Item = Result>; + + fn next(&mut self) -> Option { + while let Some(next) = self.1.next() { + let getter = |next| -> Result<(String, FileLockEntry<'a>)> { + let entry = self.0 + .get(next)? + .ok_or_else(|| CE::from_kind(CEK::StoreReadError))?; + Ok((entry.get_category()?, entry)) + }; + + match getter(next) { + Err(e) => return Some(Err(e)), + Ok((c, e)) => { + if c == self.2 { + return Some(Ok(e)) + // } else { + // continue + } + } + } + } + + None + } +} diff --git a/lib/entry/libimagentrycategory/src/lib.rs b/lib/entry/libimagentrycategory/src/lib.rs index 66f0a9c8..0f0e1189 100644 --- a/lib/entry/libimagentrycategory/src/lib.rs +++ b/lib/entry/libimagentrycategory/src/lib.rs @@ -38,14 +38,14 @@ extern crate toml_query; extern crate toml; #[macro_use] -extern crate is_match; -#[macro_use] extern crate log; #[macro_use] extern crate error_chain; extern crate libimagerror; -#[macro_use] -extern crate libimagstore; +#[macro_use] extern crate libimagstore; +extern crate libimagutil; +#[macro_use] extern crate libimagentryutil; +extern crate libimagentrylink; pub mod category; pub mod entry; diff --git a/lib/entry/libimagentrycategory/src/store.rs b/lib/entry/libimagentrycategory/src/store.rs index 4c2e26cf..5fc87347 100644 --- a/lib/entry/libimagentrycategory/src/store.rs +++ b/lib/entry/libimagentrycategory/src/store.rs @@ -26,14 +26,14 @@ use toml::Value; use libimagstore::store::Store; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; -use libimagstore::storeid::StoreIdIterator; +use libimagentryutil::isa::Is; -use category::Category; use error::CategoryErrorKind as CEK; use error::CategoryError as CE; use error::ResultExt; use error::Result; use iter::CategoryNameIter; +use category::IsCategory; pub const CATEGORY_REGISTER_NAME_FIELD_PATH : &'static str = "category.register.name"; @@ -44,7 +44,7 @@ pub trait CategoryStore { fn category_exists(&self, name: &str) -> Result; - fn create_category(&self, name: &str) -> Result; + fn create_category<'a>(&'a self, name: &str) -> Result>; fn delete_category(&self, name: &str) -> Result<()>; @@ -58,6 +58,7 @@ impl CategoryStore for Store { /// Check whether a category exists fn category_exists(&self, name: &str) -> Result { + trace!("Category exists? '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; represents_category(self, sid, name) } @@ -65,7 +66,8 @@ impl CategoryStore for Store { /// Create a category /// /// Fails if the category already exists (returns false then) - fn create_category(&self, name: &str) -> Result> { + fn create_category<'a>(&'a self, name: &str) -> Result> { + trace!("Creating category: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; let mut entry = self.create(sid)?; @@ -75,17 +77,20 @@ impl CategoryStore for Store { .get_header_mut() .insert(CATEGORY_REGISTER_NAME_FIELD_PATH, Value::String(String::from(name)))?; + trace!("Creating category worked: '{}'", name); Ok(entry) } /// Delete a category fn delete_category(&self, name: &str) -> Result<()> { + trace!("Deleting category: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; self.delete(sid).map_err(CE::from) } /// Get all category names fn all_category_names(&self) -> Result { + trace!("Getting all category names"); Ok(CategoryNameIter::new(self, self.entries()?.without_store())) } @@ -94,6 +99,7 @@ impl CategoryStore for Store { /// Returns the FileLockEntry which represents the category, so one can link to it and use it /// like a normal file in the store (which is exactly what it is). fn get_category_by_name(&self, name: &str) -> Result> { + trace!("Getting category by name: '{}'", name); let sid = mk_category_storeid(self.path().clone(), name)?; self.get(sid)