From cb0e69489cee9916c53c374e53d6594169e7817f Mon Sep 17 00:00:00 2001 From: Elias Kohout Date: Sat, 28 Dec 2024 15:51:57 +0100 Subject: [PATCH] almost finish implementation of DefaultRepository --- internal/data/DefaultRepository.go | 75 ++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/internal/data/DefaultRepository.go b/internal/data/DefaultRepository.go index 1babe10..f23bee9 100644 --- a/internal/data/DefaultRepository.go +++ b/internal/data/DefaultRepository.go @@ -1,21 +1,26 @@ package data import ( - "encoding/json" - "errors" - "strconv" + "encoding/json" + "errors" + "strconv" + "strings" ) - // Default implementation of IRepository using an IDatastore. type DefaultRepository[T IIdentifiable] struct { ds IDatastore prefix string } -// TODO docstring -func NewDefaultRepository[T IIdentifiable](ds IDatastore, prefix string) *DefaultRepository[T] { - return &DefaultRepository[T]{ ds: ds, prefix: prefix } +// Creates a new DefaultRepository for a generic type T given a IDatastore and +// a prefix. The type T must implement the IIdentifiable interface. The prefix +// will be used for the key for every entry using the created repository. The +// prefix should be not yet be in use in the given datastore and not contain a +// ':' character. +func NewDefaultRepository[T IIdentifiable](ds IDatastore, prefix string) (*DefaultRepository[T], error) { + if strings.Contains(prefix, ":") { return nil, errors.New("prefix should not contain ':'") } + return &DefaultRepository[T]{ ds: ds, prefix: prefix }, nil } // Creates a new entry in the repository with the given object t. Throws an @@ -25,7 +30,7 @@ func (repo *DefaultRepository[T]) Create(t T) error { key := repo.prefix + ":" + strconv.FormatUint(uint64(t.Id()), 10) exists, err := repo.ds.KeyExists(key) if err != nil { return err } - if exists { return errors.New("key already exits") } + if exists { return errors.New("entry with given id already exists") } d, err := json.Marshal(t) if err != nil { return err } @@ -43,7 +48,7 @@ func (repo *DefaultRepository[T]) Update(t T) error { key := repo.prefix + ":" + strconv.FormatUint(uint64(t.Id()), 10) exists, err := repo.ds.KeyExists(key) if err != nil { return err } - if !exists { return errors.New("key does not exits") } + if !exists { return errors.New("no entry with given id") } d, err := json.Marshal(t) if err != nil { return err } @@ -54,19 +59,61 @@ func (repo *DefaultRepository[T]) Update(t T) error { return nil } +// Delete the entry with the same id as t in the repository. Trows an error if +// the connection to the IDatastore fails or the key of t does not exist. func (repo *DefaultRepository[T]) Delete(t T) error { - // TODO + key := repo.prefix + ":" + strconv.FormatUint(uint64(t.Id()), 10) + + exists, err := repo.ds.KeyExists(key) + if err != nil { return err } + if !exists { return errors.New("no entry with given id") } + + err = repo.ds.Delete(key) + if err != nil { return err } + return nil } +// Get all the objects of type T from the repository as a list. Trows an error +// if the connection to the IDatastore fails. func (repo *DefaultRepository[T]) GetAll() ([]T, error) { - // TODO - return nil, nil + out := make([]T, 0) + + allkeys, err := repo.ds.GetAllKeys() + if err != nil { return nil, err } + + for key, _ := range allkeys { + splitkey := strings.Split(key, ":") + if splitkey[0] == repo.prefix { + + // convert id to an int + id, err := strconv.ParseUint(splitkey[1], 10, 0) + if err != nil { return nil, err } + + // retrieve the object + obj, err := repo.GetById(uint(id)) + if err != nil { return nil, err } + out = append(out, obj) + + } + } + + return out, nil } +// Get the objects of type T from the repository that has the given id. Trows an error +// if the connection to the IDatastore or the decoding process fails. func (repo *DefaultRepository[T]) GetById(id uint) (T, error) { - // TODO - return *new(T), nil + var obj T + + key := repo.prefix + ":" + strconv.FormatUint(uint64(id), 10) + value, err := repo.ds.Get(key) + if err != nil { return obj, err } + + err = json.Unmarshal([]byte(value), &obj) + if err != nil { return obj, err } + + return obj, nil } func (repo *DefaultRepository[T]) GetByCriteria(c ISearchCriteria[T]) ([]T, error) {