summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-11-04 20:34:55 +0100
committerMatthias Beyer <mail@beyermatthias.de>2019-11-09 17:35:19 +0100
commit5be95227c4e2143a82a7576e3d2beba17f373dd5 (patch)
treef8446f5758e193b0cff4355cf4362eec8337ad45
parent7873d99df51762c795589da66348e21bb74cfb5f (diff)
Add builder for todo entries
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--lib/domain/libimagtodo/src/builder.rs130
-rw-r--r--lib/domain/libimagtodo/src/lib.rs1
-rw-r--r--lib/domain/libimagtodo/src/store.rs54
3 files changed, 151 insertions, 34 deletions
diff --git a/lib/domain/libimagtodo/src/builder.rs b/lib/domain/libimagtodo/src/builder.rs
new file mode 100644
index 0000000..45cc45a
--- /dev/null
+++ b/lib/domain/libimagtodo/src/builder.rs
@@ -0,0 +1,130 @@
+//
+// 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 chrono::NaiveDateTime;
+use failure::Fallible as Result;
+use failure::err_msg;
+use toml_query::insert::TomlValueInsertExt;
+use uuid::Uuid;
+
+use libimagstore::store::Store;
+use libimagstore::store::FileLockEntry;
+use libimagentryutil::isa::Is;
+use libimagutil::date::datetime_to_string;
+
+use crate::priority::Priority;
+use crate::status::Status;
+use crate::entry::IsTodo;
+use crate::entry::TodoHeader;
+use crate::store::date_sanity_check;
+
+
+pub struct TodoBuilder {
+ uuid: Option<Uuid>,
+ status: Option<Status>,
+ scheduled: Option<NaiveDateTime>,
+ hidden: Option<NaiveDateTime>,
+ due: Option<NaiveDateTime>,
+ prio: Option<Priority>,
+ check_sanity: bool,
+}
+
+impl TodoBuilder {
+ pub(crate) fn new() -> Self {
+ TodoBuilder {
+ uuid: None,
+ status: None,
+ scheduled: None,
+ hidden: None,
+ due: None,
+ prio: None,
+ check_sanity: true,
+ }
+ }
+
+ pub fn build<'a>(self, store: &'a Store) -> Result<FileLockEntry<'a>> {
+ let uuid = self.uuid.ok_or_else(|| err_msg("Uuid missing"))?;
+ let status = self.status.ok_or_else(|| err_msg("Status missing"))?;
+
+ if self.check_sanity {
+ trace!("Checking sanity before creating todo");
+ if let Err(s) = date_sanity_check(self.scheduled.as_ref(), self.hidden.as_ref(), self.due.as_ref()) {
+ trace!("Not sane.");
+ return Err(format_err!("{}", s))
+ }
+ }
+
+ let uuid_s = format!("{}", uuid.to_hyphenated_ref()); // TODO: not how it is supposed to be
+ debug!("Created new UUID for todo = {}", uuid_s);
+
+ let mut entry = crate::module_path::new_id(uuid_s).and_then(|id| store.create(id))?;
+
+ let header = TodoHeader {
+ uuid,
+ status,
+ scheduled: self.scheduled.as_ref().map(datetime_to_string),
+ hidden: self.hidden.as_ref().map(datetime_to_string),
+ due: self.due.as_ref().map(datetime_to_string),
+ priority: self.prio
+ };
+
+ debug!("Created header for todo: {:?}", header);
+
+ let _ = entry.get_header_mut().insert_serialized("todo", header)?;
+ let _ = entry.set_isflag::<IsTodo>()?;
+
+ Ok(entry)
+ }
+
+ pub fn with_uuid(mut self, uuid: Option<Uuid>) -> Self {
+ self.uuid = uuid;
+ self
+ }
+
+ pub fn with_status(mut self, status: Option<Status>) -> Self {
+ self.status = status;
+ self
+ }
+
+ pub fn with_scheduled(mut self, scheduled: Option<NaiveDateTime>) -> Self {
+ self.scheduled = scheduled;
+ self
+ }
+
+ pub fn with_hidden(mut self, hidden: Option<NaiveDateTime>) -> Self {
+ self.hidden = hidden;
+ self
+ }
+
+ pub fn with_due(mut self, due: Option<NaiveDateTime>) -> Self {
+ self.due = due;
+ self
+ }
+
+ pub fn with_prio(mut self, prio: Option<Priority>) -> Self {
+ self.prio = prio;
+ self
+ }
+
+ pub fn with_check_sanity(mut self, b: bool) -> Self {
+ self.check_sanity = b;
+ self
+ }
+
+}
diff --git a/lib/domain/libimagtodo/src/lib.rs b/lib/domain/libimagtodo/src/lib.rs
index 8901077..40cf5a8 100644
--- a/lib/domain/libimagtodo/src/lib.rs
+++ b/lib/domain/libimagtodo/src/lib.rs
@@ -34,6 +34,7 @@ extern crate libimagutil;
#[macro_use] extern crate libimagstore;
#[macro_use] extern crate libimagentryutil;
+pub mod builder;
pub mod entry;
pub mod iter;
pub mod priority;
diff --git a/lib/domain/libimagtodo/src/store.rs b/lib/domain/libimagtodo/src/store.rs
index cc1f2aa..0aec566 100644
--- a/lib/domain/libimagtodo/src/store.rs
+++ b/lib/domain/libimagtodo/src/store.rs
@@ -22,20 +22,19 @@ use std::result::Result as RResult;
use failure::Fallible as Result;
use chrono::NaiveDateTime;
use uuid::Uuid;
-use toml_query::insert::TomlValueInsertExt;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::iter::Entries;
-use libimagutil::date::datetime_to_string;
-use libimagentryutil::isa::Is;
use crate::status::Status;
use crate::priority::Priority;
-use crate::entry::TodoHeader;
-use crate::entry::IsTodo;
+use crate::builder::TodoBuilder;
pub trait TodoStore<'a> {
+
+ fn todo_builder(&self) -> TodoBuilder;
+
fn create_todo(&'a self,
status: Status,
scheduled: Option<NaiveDateTime>,
@@ -51,6 +50,13 @@ pub trait TodoStore<'a> {
impl<'a> TodoStore<'a> for Store {
+ /// Get a TodoBuilder instance, which can be used to build a todo object.
+ ///
+ /// The TodoBuilder::new() constructor is not exposed, this function should be used instead.
+ fn todo_builder(&self) -> TodoBuilder {
+ TodoBuilder::new()
+ }
+
/// Create a new todo entry
///
/// # Warning
@@ -70,35 +76,15 @@ impl<'a> TodoStore<'a> for Store {
prio: Option<Priority>,
check_sanity: bool) -> Result<FileLockEntry<'a>>
{
- if check_sanity {
- trace!("Checking sanity before creating todo");
- if let Err(s) = date_sanity_check(scheduled.as_ref(), hidden.as_ref(), due.as_ref()) {
- trace!("Not sane.");
- return Err(format_err!("{}", s))
- }
- }
-
- let uuid = Uuid::new_v4();
- let uuid_s = format!("{}", uuid.to_hyphenated_ref()); // TODO: not how it is supposed to be
- debug!("Created new UUID for todo = {}", uuid_s);
-
- let mut entry = crate::module_path::new_id(uuid_s).and_then(|id| self.create(id))?;
-
- let header = TodoHeader {
- uuid,
- status,
- scheduled: scheduled.as_ref().map(datetime_to_string),
- hidden: hidden.as_ref().map(datetime_to_string),
- due: due.as_ref().map(datetime_to_string),
- priority: prio
- };
-
- debug!("Created header for todo: {:?}", header);
-
- let _ = entry.get_header_mut().insert_serialized("todo", header)?;
- let _ = entry.set_isflag::<IsTodo>()?;
-
- Ok(entry)
+ TodoBuilder::new()
+ .with_status(Some(status))
+ .with_uuid(Some(Uuid::new_v4()))
+ .with_scheduled(scheduled)
+ .with_hidden(hidden)
+ .with_due(due)
+ .with_prio(prio)
+ .with_check_sanity(check_sanity)
+ .build(&self)
}
fn get_todo_by_uuid(&'a self, uuid: &Uuid) -> Result<Option<FileLockEntry<'a>>> {