Introduced interfaces for all repositories, completely isolating the persistence layer from the repositories usage and specification

This commit is contained in:
Deluan
2016-03-02 09:33:49 -05:00
parent 272a499c7e
commit 300ed0d9a4
15 changed files with 83 additions and 48 deletions
+6 -6
View File
@@ -4,24 +4,24 @@ import (
"github.com/deluan/gosonic/domain"
)
type Album struct {
BaseRepository
type albumRepository struct {
baseRepository
}
func NewAlbumRepository() *Album {
r := &Album{}
func NewAlbumRepository() domain.AlbumRepository {
r := &albumRepository{}
r.init("album", &domain.Album{})
return r
}
func (r *Album) Put(m *domain.Album) error {
func (r *albumRepository) Put(m *domain.Album) error {
if m.Id == "" {
m.Id = r.NewId(m.ArtistId, m.Name)
}
return r.saveOrUpdate(m.Id, m)
}
func (r *Album) Get(id string) (*domain.Album, error) {
func (r *albumRepository) Get(id string) (*domain.Album, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*domain.Album), err
+7 -7
View File
@@ -4,30 +4,30 @@ import (
"github.com/deluan/gosonic/domain"
)
type Artist struct {
BaseRepository
type artistRepository struct {
baseRepository
}
func NewArtistRepository() *Artist {
r := &Artist{}
func NewArtistRepository() domain.ArtistRepository {
r := &artistRepository{}
r.init("artist", &domain.Artist{})
return r
}
func (r *Artist) Put(m *domain.Artist) error {
func (r *artistRepository) Put(m *domain.Artist) error {
if m.Id == "" {
m.Id = r.NewId(m.Name)
}
return r.saveOrUpdate(m.Id, m)
}
func (r *Artist) Get(id string) (*domain.Artist, error) {
func (r *artistRepository) Get(id string) (*domain.Artist, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*domain.Artist), err
}
func (r *Artist) GetByName(name string) (*domain.Artist, error) {
func (r *artistRepository) GetByName(name string) (*domain.Artist, error) {
id := r.NewId(name)
return r.Get(id)
}
+11 -11
View File
@@ -9,13 +9,13 @@ import (
"reflect"
)
type BaseRepository struct {
type baseRepository struct {
table string
entityType reflect.Type
fieldNames []string
}
func (r *BaseRepository) init(table string, entity interface{}) {
func (r *baseRepository) init(table string, entity interface{}) {
r.table = table
r.entityType = reflect.TypeOf(entity).Elem()
@@ -29,17 +29,17 @@ func (r *BaseRepository) init(table string, entity interface{}) {
}
// TODO Use annotations to specify fields to be used
func (r *BaseRepository) NewId(fields ...string) string {
func (r *baseRepository) NewId(fields ...string) string {
s := fmt.Sprintf("%s\\%s", strings.ToUpper(r.table), strings.Join(fields, ""))
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}
func (r *BaseRepository) CountAll() (int, error) {
func (r *baseRepository) CountAll() (int, error) {
ids, err := db().SMembers([]byte(r.table + "s:all"))
return len(ids), err
}
func (r *BaseRepository) saveOrUpdate(id string, entity interface{}) error {
func (r *baseRepository) saveOrUpdate(id string, entity interface{}) error {
recordPrefix := fmt.Sprintf("%s:%s:", r.table, id)
allKey := r.table + "s:all"
@@ -68,7 +68,7 @@ func (r *BaseRepository) saveOrUpdate(id string, entity interface{}) error {
}
// TODO Optimize
func (r *BaseRepository) getParent(entity interface{}) (table string, id string) {
func (r *baseRepository) getParent(entity interface{}) (table string, id string) {
dt := reflect.TypeOf(entity).Elem()
for i := 0; i < dt.NumField(); i++ {
f := dt.Field(i)
@@ -81,7 +81,7 @@ func (r *BaseRepository) getParent(entity interface{}) (table string, id string)
return "", ""
}
func (r *BaseRepository) getFieldKeys(id string) [][]byte {
func (r *baseRepository) getFieldKeys(id string) [][]byte {
recordPrefix := fmt.Sprintf("%s:%s:", r.table, id)
var fieldKeys = make([][]byte, len(r.fieldNames))
for i, n := range r.fieldNames {
@@ -90,11 +90,11 @@ func (r *BaseRepository) getFieldKeys(id string) [][]byte {
return fieldKeys
}
func (r* BaseRepository) newInstance() interface{} {
func (r*baseRepository) newInstance() interface{} {
return reflect.New(r.entityType).Interface()
}
func (r *BaseRepository) readEntity(id string) (interface{}, error) {
func (r *baseRepository) readEntity(id string) (interface{}, error) {
entity := r.newInstance()
fieldKeys := r.getFieldKeys(id)
@@ -107,7 +107,7 @@ func (r *BaseRepository) readEntity(id string) (interface{}, error) {
return entity, err
}
func (r *BaseRepository) toEntity(response [][]byte, entity interface{}) error {
func (r *baseRepository) toEntity(response [][]byte, entity interface{}) error {
var record = make(map[string]interface{}, len(response))
for i, v := range response {
var value interface{}
@@ -121,7 +121,7 @@ func (r *BaseRepository) toEntity(response [][]byte, entity interface{}) error {
}
// TODO Optimize it! Probably very slow (and confusing!)
func (r *BaseRepository) loadAll(entities interface{}, sortBy string) error {
func (r *baseRepository) loadAll(entities interface{}, sortBy string) error {
total, err := r.CountAll()
if (err != nil) {
return err
+2 -2
View File
@@ -19,8 +19,8 @@ func shouldBeEqual(actualStruct interface{}, expectedStruct ...interface{}) stri
return ShouldEqual(actual, expected)
}
func createRepo() *BaseRepository{
repo := &BaseRepository{}
func createRepo() *baseRepository {
repo := &baseRepository{}
repo.init("test", &TestEntity{})
return repo
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
type artistIndex struct {
BaseRepository
baseRepository
}
func NewArtistIndexRepository() domain.ArtistIndexRepository {
+5 -5
View File
@@ -4,16 +4,16 @@ import (
"github.com/deluan/gosonic/domain"
)
type MediaFile struct {
BaseRepository
type mediaFileRepository struct {
baseRepository
}
func NewMediaFileRepository() *MediaFile {
r := &MediaFile{}
func NewMediaFileRepository() domain.MediaFileRepository {
r := &mediaFileRepository{}
r.init("mediafile", &domain.MediaFile{})
return r
}
func (r *MediaFile) Put(m *domain.MediaFile) error {
func (r *mediaFileRepository) Put(m *domain.MediaFile) error {
return r.saveOrUpdate(m.Id, m)
}
+8 -6
View File
@@ -5,16 +5,18 @@ import (
"github.com/astaxie/beego"
)
type MediaFolder struct {}
type mediaFolderRepository struct {
domain.MediaFolderRepository
}
func NewMediaFolderRepository() *MediaFolder {
return &MediaFolder{}
func NewMediaFolderRepository() domain.MediaFolderRepository {
return &mediaFolderRepository{}
}
func (*MediaFolder) GetAll() ([]*domain.MediaFolder, error) {
func (*mediaFolderRepository) GetAll() ([]domain.MediaFolder, error) {
mediaFolder := domain.MediaFolder{Id: "0", Name: "iTunes Library", Path: beego.AppConfig.String("musicFolder")}
result := make([]*domain.MediaFolder, 1)
result[0] = &mediaFolder
result := make([]domain.MediaFolder, 1)
result[0] = mediaFolder
return result, nil
}
+7 -7
View File
@@ -5,17 +5,17 @@ import (
"errors"
)
type property struct {
BaseRepository
type propertyRepository struct {
baseRepository
}
func NewPropertyRepository() *property {
r := &property{}
func NewPropertyRepository() domain.PropertyRepository {
r := &propertyRepository{}
r.init("property", &domain.Property{})
return r
}
func (r *property) Put(id string, value string) error {
func (r *propertyRepository) Put(id string, value string) error {
m := &domain.Property{Id: id, Value: value}
if m.Id == "" {
return errors.New("Id is required")
@@ -23,13 +23,13 @@ func (r *property) Put(id string, value string) error {
return r.saveOrUpdate(m.Id, m)
}
func (r *property) Get(id string) (string, error) {
func (r *propertyRepository) Get(id string) (string, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*domain.Property).Value, err
}
func (r*property) DefaultGet(id string, defaultValue string) (string, error) {
func (r*propertyRepository) DefaultGet(id string, defaultValue string) (string, error) {
v, err := r.Get(id)
if v == "" {