package gime import ( "errors" "strconv" "time" "github.com/br0xen/boltease" ) // FindTimeEntryByUUID searches all entries of type tp (can be TypeUnknown) // for the time entry with the given uuid func (gdb *GimeDB) FindTimeEntryByUUID(tp, uuid string) (*TimeEntry, error) { var ret *TimeEntry var err error if tp == TypeUnknown { for _, v := range AllTypes { ret, err = gdb.FindTimeEntryByUUID(v, uuid) if ret != nil { return ret, nil } } return nil, errors.New("Unable to find time entry with uuid " + uuid) } tstEntries := gdb.dbGetAllTimeEntries(tp) for i := range tstEntries { if tstEntries[i].uuid == uuid { // Found it! return tstEntries[i], nil } } return nil, errors.New("Unable to find time entry with uuid " + uuid) } // SaveTimeEntry creates a time entry in the database // If TimeEntry.end is zero, then it puts it in TypeCurrent func (gdb *GimeDB) SaveTimeEntry(te *TimeEntry) error { var err error var useDb *boltease.DB tp := TypeRecent if te.end.IsZero() { // Currently running tp = TypeCurrent useDb, err = gdb.openDBType(tp) if err != nil { return err } } else { // We have an end time. Does this entry go in 'recent' or 'archive' // We shove times that happened 30 days ago into 'archive' if time.Since(te.end) > (time.Hour * 24 * 30) { tp = TypeArchive } } tePath := []string{tp, te.start.Format(time.RFC3339)} if err = useDb.SetValue(tePath, "uuid", te.uuid); err != nil { return err } if err = useDb.SetTimestamp(tePath, "start", te.start); err != nil { return err } if err = useDb.SetTimestamp(tePath, "end", te.end); err != nil { return err } for i := 0; i < te.tags.Length(); i++ { err = useDb.SetValue(append(tePath, "tags"), strconv.Itoa(i), te.tags.Get(i)) } return nil } // UpdateTimeEntry updates the time entry in the database // It first finds the current entry in the database by the uuid func (gdb *GimeDB) UpdateTimeEntry(te *TimeEntry) error { var err error if te.uuid == "" { return errors.New("Given time entry has no uuid") } oldTe, err := gdb.FindTimeEntryByUUID(TypeUnknown, te.uuid) if err != nil { return err } } // RemoveTimeEntry removes a time entry of type tp (can be TypeUnknown) // with the given uuid from the database func (gdb *GimeDB) RemoveTimeEntry(tp, uuid string) error { var fndEntry *TimeEntry var err error // For TypeUnknown, we want to manually loop, so we know where we found it if tp == TypeUnknown { for _, v := range AllTypes { fndEntry, err = gdb.FindTimeEntryByUUID(v, uuid) if err == nil { tp = v break } } if fndEntry == nil { return errors.New("Unable to find time entry with uuid " + uuid) } } var useDb *boltease.DB var err error if useDb, err = gdb.openDBType(tp); err != nil { return ret } defer gdb.closeDBType(tp) return nil, errors.New("Unable to find time entry with uuid " + uuid) } // dbGetAllTimeEntries gets all time entries of a specific type // tp can be: // TypeCurrent = "current" // TypeRecent = "recent" // TypeArchive = "archive" // TypeUnknown = "unknown" - Returns _ALL_ entries // Getting all archived time entries has the potential to be a lot of data func (gdb *GimeDB) dbGetAllTimeEntries(tp string) []TimeEntry { var ret []TimeEntry if tp == TypeUnknown { for _, v := range AllTypes { ret = append(ret, gdb.dbGetAllTimeEntries(v)) } return ret } var useDb *boltease.DB var err error if useDb, err = gdb.openDBType(tp); err != nil { return ret } defer gdb.closeDBType(tp) var sttimes []string if sttimes, err = useDb.GetBucketList([]string{tp}); err != nil { return ret } for _, v := range sttimes { if te, _ := gdb.dbGetTimeEntry(tp, v); te != nil { ret = append(ret, *te) } } return ret } // dbGetTimeEntry pulls a time entry of type tp with the given id // from the db and returns it. func (gdb *GimeDB) dbGetTimeEntry(tp, sttm string) (*TimeEntry, error) { var ret *TimeEntry var err error if tp == TypeUnknown { // Loop through the types and return the first entry found that matches for _, v := range AllTypes { ret, _ = gdb.dbGetTimeEntry(v, sttm) if ret != nil { return ret, nil } } return nil, errors.Error("Couldn't find time entry") } var useDb *boltease.DB if useDb, err = gdb.openDBType(tp); err != nil { return ret, err } defer gdb.closeDBType(tp) entryPath := []string{tp, sttm} ret = new(TimeEntry) if ret.uuid, err = useDb.GetValue(entryPath, "uuid"); err != nil { return nil, errors.New("Unable to read entry uuid") } if ret.start, err = useDb.GetTimestamp(entryPath, "start"); err != nil { return nil, errors.New("Unable to read entry start time") } if ret.end, err = useDb.GetTimestamp(entryPath, "end"); err != nil { return nil, errors.New("Unable to read entry end time") } var keys []string entryTagsPath := append(entryPath, "tags") if keys, err = useDb.GetKeyList(entryTagsPath); err != nil { keys = []string{} } ret.tags = new(TagCollection) for i := range keys { var val string if val, err = useDb.GetValue(entryTagsPath, keys[i]); err == nil { ret.tags.Push(val) } } return ret, nil }