Refactoring to a cleaner architecture

This commit is contained in:
Deluan 2016-03-02 09:07:24 -05:00
parent 74478ce6f9
commit 272a499c7e
27 changed files with 120 additions and 120 deletions

View File

@ -2,18 +2,18 @@ package api
import (
"github.com/astaxie/beego"
"github.com/deluan/gosonic/repositories"
"github.com/deluan/gosonic/utils"
"github.com/karlkfi/inject"
"github.com/deluan/gosonic/api/responses"
"github.com/deluan/gosonic/consts"
"strconv"
"github.com/deluan/gosonic/domain"
)
type GetIndexesController struct {
beego.Controller
repo repositories.ArtistIndex
properties repositories.Property
repo domain.ArtistIndexRepository
properties domain.PropertyRepository
}
func (c *GetIndexesController) Prepare() {

View File

@ -6,11 +6,11 @@ import (
"github.com/deluan/gosonic/utils"
. "github.com/smartystreets/goconvey/convey"
"github.com/deluan/gosonic/tests"
"github.com/deluan/gosonic/repositories"
"encoding/xml"
"github.com/deluan/gosonic/api/responses"
"github.com/deluan/gosonic/consts"
"github.com/deluan/gosonic/tests/mocks"
"github.com/deluan/gosonic/domain"
)
const (
@ -20,11 +20,11 @@ const (
func TestGetIndexes(t *testing.T) {
tests.Init(t, false)
mockRepo := mocks.CreateMockArtistIndexRepo()
utils.DefineSingleton(new(repositories.ArtistIndex), func() repositories.ArtistIndex {
utils.DefineSingleton(new(domain.ArtistIndexRepository), func() domain.ArtistIndexRepository {
return mockRepo
})
propRepo := mocks.CreateMockPropertyRepo()
utils.DefineSingleton(new(repositories.Property), func() repositories.Property {
utils.DefineSingleton(new(domain.PropertyRepository), func() domain.PropertyRepository {
return propRepo
})

View File

@ -3,13 +3,13 @@ package api
import (
"github.com/astaxie/beego"
"github.com/deluan/gosonic/api/responses"
"github.com/deluan/gosonic/repositories"
"github.com/deluan/gosonic/persistence"
)
type GetMusicFoldersController struct{ beego.Controller }
func (c *GetMusicFoldersController) Get() {
repository := repositories.NewMediaFolderRepository()
repository := persistence.NewMediaFolderRepository()
mediaFolderList, _ := repository.GetAll()
folders := make([]responses.MusicFolder, len(mediaFolderList))
for i, f := range mediaFolderList {

View File

@ -2,10 +2,11 @@ package conf
import (
"github.com/deluan/gosonic/utils"
"github.com/deluan/gosonic/repositories"
"github.com/deluan/gosonic/persistence"
"github.com/deluan/gosonic/domain"
)
func init () {
utils.DefineSingleton(new(repositories.ArtistIndex), repositories.NewArtistIndexRepository)
utils.DefineSingleton(new(repositories.Property), repositories.NewPropertyRepository)
utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository)
}

View File

@ -1,4 +1,4 @@
package models
package domain
type Album struct {
Id string

View File

@ -1,4 +1,4 @@
package models
package domain
type Artist struct {
Id string

18
domain/index.go Normal file
View File

@ -0,0 +1,18 @@
package domain
type ArtistInfo struct {
ArtistId string
Artist string
}
type ArtistIndex struct {
Id string
Artists []ArtistInfo
}
type ArtistIndexRepository interface {
Put(m *ArtistIndex) error
Get(id string) (*ArtistIndex, error)
GetAll() ([]ArtistIndex, error)
}

View File

@ -1,4 +1,4 @@
package models
package domain
import (
"time"

View File

@ -1,4 +1,4 @@
package models
package domain
type MediaFolder struct {
Id string

13
domain/property.go Normal file
View File

@ -0,0 +1,13 @@
package domain
type Property struct {
Id string
Value string
}
type PropertyRepository interface {
Put(id string, value string) error
Get(id string) (string, error)
DefaultGet(id string, defaultValue string) (string, error)
}

View File

@ -1,13 +0,0 @@
package models
type ArtistInfo struct {
ArtistId string
Artist string
}
type ArtistIndex struct {
Id string
Artists []ArtistInfo
}

View File

@ -1,6 +0,0 @@
package models
type Property struct {
Id string
Value string
}

View File

@ -1,7 +1,7 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
)
type Album struct {
@ -10,19 +10,19 @@ type Album struct {
func NewAlbumRepository() *Album {
r := &Album{}
r.init("album", &models.Album{})
r.init("album", &domain.Album{})
return r
}
func (r *Album) Put(m *models.Album) error {
func (r *Album) 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) (*models.Album, error) {
func (r *Album) Get(id string) (*domain.Album, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*models.Album), err
return rec.(*domain.Album), err
}

View File

@ -1,7 +1,7 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
)
type Artist struct {
@ -10,24 +10,24 @@ type Artist struct {
func NewArtistRepository() *Artist {
r := &Artist{}
r.init("artist", &models.Artist{})
r.init("artist", &domain.Artist{})
return r
}
func (r *Artist) Put(m *models.Artist) error {
func (r *Artist) 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) (*models.Artist, error) {
func (r *Artist) Get(id string) (*domain.Artist, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*models.Artist), err
return rec.(*domain.Artist), err
}
func (r *Artist) GetByName(name string) (*models.Artist, error) {
func (r *Artist) GetByName(name string) (*domain.Artist, error) {
id := r.NewId(name)
return r.Get(id)
}

View File

@ -1,4 +1,4 @@
package repositories
package persistence
import (
"fmt"

View File

@ -1,4 +1,4 @@
package repositories
package persistence
import (
"testing"

View File

@ -1,29 +1,23 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"errors"
"sort"
"github.com/deluan/gosonic/utils"
)
type ArtistIndex interface {
Put(m *models.ArtistIndex) error
Get(id string) (*models.ArtistIndex, error)
GetAll() ([]models.ArtistIndex, error)
}
type artistIndex struct {
BaseRepository
}
func NewArtistIndexRepository() ArtistIndex {
func NewArtistIndexRepository() domain.ArtistIndexRepository {
r := &artistIndex{}
r.init("index", &models.ArtistIndex{})
r.init("index", &domain.ArtistIndex{})
return r
}
func (r *artistIndex) Put(m *models.ArtistIndex) error {
func (r *artistIndex) Put(m *domain.ArtistIndex) error {
if m.Id == "" {
return errors.New("Id is not set")
}
@ -31,19 +25,19 @@ func (r *artistIndex) Put(m *models.ArtistIndex) error {
return r.saveOrUpdate(m.Id, m)
}
func (r *artistIndex) Get(id string) (*models.ArtistIndex, error) {
func (r *artistIndex) Get(id string) (*domain.ArtistIndex, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*models.ArtistIndex), err
return rec.(*domain.ArtistIndex), err
}
func (r *artistIndex) GetAll() ([]models.ArtistIndex, error) {
var indices = make([]models.ArtistIndex, 0)
func (r *artistIndex) GetAll() ([]domain.ArtistIndex, error) {
var indices = make([]domain.ArtistIndex, 0)
err := r.loadAll(&indices, "")
return indices, err
}
type byArtistName []models.ArtistInfo
type byArtistName []domain.ArtistInfo
func (a byArtistName) Len() int {
return len(a)

View File

@ -1,10 +1,10 @@
package repositories
package persistence
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/deluan/gosonic/tests"
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"strconv"
)
@ -16,7 +16,7 @@ func TestIndexRepository(t *testing.T) {
repo := NewArtistIndexRepository()
Convey("It should be able to read and write to the database", func() {
i := &models.ArtistIndex{Id: "123"}
i := &domain.ArtistIndex{Id: "123"}
repo.Put(i)
s,_ := repo.Get("123")
@ -24,7 +24,7 @@ func TestIndexRepository(t *testing.T) {
So(s, shouldBeEqual, i)
})
Convey("Method Put() should return error if Id is not set", func() {
i := &models.ArtistIndex{}
i := &domain.ArtistIndex{}
err := repo.Put(i)
@ -32,7 +32,7 @@ func TestIndexRepository(t *testing.T) {
})
Convey("Given that I have 4 records", func() {
for i := 1; i <= 4; i++ {
e := &models.ArtistIndex{Id: strconv.Itoa(i)}
e := &domain.ArtistIndex{Id: strconv.Itoa(i)}
repo.Put(e)
}

View File

@ -1,4 +1,4 @@
package repositories
package persistence
import (
"sync"

View File

@ -1,7 +1,7 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
)
type MediaFile struct {
@ -10,10 +10,10 @@ type MediaFile struct {
func NewMediaFileRepository() *MediaFile {
r := &MediaFile{}
r.init("mediafile", &models.MediaFile{})
r.init("mediafile", &domain.MediaFile{})
return r
}
func (r *MediaFile) Put(m *models.MediaFile) error {
func (r *MediaFile) Put(m *domain.MediaFile) error {
return r.saveOrUpdate(m.Id, m)
}

View File

@ -1,7 +1,7 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"github.com/astaxie/beego"
)
@ -12,9 +12,9 @@ func NewMediaFolderRepository() *MediaFolder {
}
func (*MediaFolder) GetAll() ([]*models.MediaFolder, error) {
mediaFolder := models.MediaFolder{Id: "0", Name: "iTunes Library", Path: beego.AppConfig.String("musicFolder")}
result := make([]*models.MediaFolder, 1)
func (*MediaFolder) 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
return result, nil
}

View File

@ -1,28 +1,22 @@
package repositories
package persistence
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"errors"
)
type Property interface {
Put(id string, value string) error
Get(id string) (string, error)
DefaultGet(id string, defaultValue string) (string, error)
}
type property struct {
BaseRepository
}
func NewPropertyRepository() *property {
r := &property{}
r.init("property", &models.Property{})
r.init("property", &domain.Property{})
return r
}
func (r *property) Put(id string, value string) error {
m := &models.Property{Id: id, Value: value}
m := &domain.Property{Id: id, Value: value}
if m.Id == "" {
return errors.New("Id is required")
}
@ -32,7 +26,7 @@ func (r *property) Put(id string, value string) error {
func (r *property) Get(id string) (string, error) {
var rec interface{}
rec, err := r.readEntity(id)
return rec.(*models.Property).Value, err
return rec.(*domain.Property).Value, err
}
func (r*property) DefaultGet(id string, defaultValue string) (string, error) {

View File

@ -2,8 +2,8 @@ package scanner
import (
"github.com/astaxie/beego"
"github.com/deluan/gosonic/repositories"
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/persistence"
"github.com/deluan/gosonic/domain"
"strings"
"github.com/deluan/gosonic/utils"
"github.com/deluan/gosonic/consts"
@ -15,7 +15,7 @@ type Scanner interface {
LoadFolder(path string) []Track
}
type tempIndex map[string]models.ArtistInfo
type tempIndex map[string]domain.ArtistInfo
// TODO Implement a flag 'isScanning'.
func StartImport() {
@ -31,9 +31,9 @@ func doImport(mediaFolder string, scanner Scanner) {
func importLibrary(files []Track) (err error){
indexGroups := utils.ParseIndexGroups(beego.AppConfig.String("indexGroups"))
mfRepo := repositories.NewMediaFileRepository()
albumRepo := repositories.NewAlbumRepository()
artistRepo := repositories.NewArtistRepository()
mfRepo := persistence.NewMediaFileRepository()
albumRepo := persistence.NewAlbumRepository()
artistRepo := persistence.NewArtistRepository()
var artistIndex = make(map[string]tempIndex)
for _, t := range files {
@ -54,7 +54,7 @@ func importLibrary(files []Track) (err error){
beego.Info("Total MediaFiles in database:", c)
if err == nil {
propertyRepo := repositories.NewPropertyRepository()
propertyRepo := persistence.NewPropertyRepository()
millis := time.Now().UnixNano() / 1000000
propertyRepo.Put(consts.LastScan, fmt.Sprint(millis))
beego.Info("LastScan timestamp:", millis)
@ -63,8 +63,8 @@ func importLibrary(files []Track) (err error){
return err
}
func parseTrack(t *Track) (*models.MediaFile, *models.Album, *models.Artist) {
mf := &models.MediaFile{
func parseTrack(t *Track) (*domain.MediaFile, *domain.Album, *domain.Artist) {
mf := &domain.MediaFile{
Id: t.Id,
Album: t.Album,
Artist: t.Artist,
@ -76,20 +76,20 @@ func parseTrack(t *Track) (*models.MediaFile, *models.Album, *models.Artist) {
UpdatedAt: t.UpdatedAt,
}
album := &models.Album{
album := &domain.Album{
Name: t.Album,
Year: t.Year,
Compilation: t.Compilation,
}
artist := &models.Artist{
artist := &domain.Artist{
Name: t.RealArtist(),
}
return mf, album, artist
}
func persist(mfRepo *repositories.MediaFile, mf *models.MediaFile, albumRepo *repositories.Album, album *models.Album, artistRepo *repositories.Artist, artist *models.Artist) {
func persist(mfRepo *persistence.MediaFile, mf *domain.MediaFile, albumRepo *persistence.Album, album *domain.Album, artistRepo *persistence.Artist, artist *domain.Artist) {
if err := artistRepo.Put(artist); err != nil {
beego.Error(err)
}
@ -105,7 +105,7 @@ func persist(mfRepo *repositories.MediaFile, mf *models.MediaFile, albumRepo *re
}
}
func collectIndex(ig utils.IndexGroups, a *models.Artist, artistIndex map[string]tempIndex) {
func collectIndex(ig utils.IndexGroups, a *domain.Artist, artistIndex map[string]tempIndex) {
name := a.Name
indexName := strings.ToLower(utils.NoArticle(name))
if indexName == "" {
@ -117,7 +117,7 @@ func collectIndex(ig utils.IndexGroups, a *models.Artist, artistIndex map[string
artists = make(tempIndex)
artistIndex[group] = artists
}
artists[indexName] = models.ArtistInfo{ArtistId: a.Id, Artist: a.Name}
artists[indexName] = domain.ArtistInfo{ArtistId: a.Id, Artist: a.Name}
}
func findGroup(ig utils.IndexGroups, name string) string {
@ -131,10 +131,10 @@ func findGroup(ig utils.IndexGroups, name string) string {
}
func saveIndex(artistIndex map[string]tempIndex) error {
idxRepo := repositories.NewArtistIndexRepository()
idxRepo := persistence.NewArtistIndexRepository()
for k, temp := range artistIndex {
idx := &models.ArtistIndex{Id: k}
idx := &domain.ArtistIndex{Id: k}
for _, v := range temp {
idx.Artists = append(idx.Artists, v)
}

View File

@ -4,7 +4,7 @@ import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/deluan/gosonic/utils"
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"github.com/deluan/gosonic/tests"
)
@ -14,7 +14,7 @@ func TestCollectIndex(t *testing.T) {
ig := utils.IndexGroups{"A":"A", "B":"B", "Tom":"Tom", "X":"X-Z"}
Convey("Simple Name", t, func() {
a := &models.Artist{Name: "Björk"}
a := &domain.Artist{Name: "Björk"}
artistIndex := make(map[string]tempIndex)
collectIndex(ig, a, artistIndex)
@ -28,7 +28,7 @@ func TestCollectIndex(t *testing.T) {
})
Convey("Name not in the index", t, func() {
a := &models.Artist{Name: "Kraftwerk"}
a := &domain.Artist{Name: "Kraftwerk"}
artistIndex := make(map[string]tempIndex)
collectIndex(ig, a, artistIndex)
@ -42,7 +42,7 @@ func TestCollectIndex(t *testing.T) {
})
Convey("Name starts with an article", t, func() {
a := &models.Artist{Name: "The The"}
a := &domain.Artist{Name: "The The"}
artistIndex := make(map[string]tempIndex)
collectIndex(ig, a, artistIndex)
@ -56,7 +56,7 @@ func TestCollectIndex(t *testing.T) {
})
Convey("Name match a multichar entry", t, func() {
a := &models.Artist{Name: "Tom Waits"}
a := &domain.Artist{Name: "Tom Waits"}
artistIndex := make(map[string]tempIndex)
collectIndex(ig, a, artistIndex)

View File

@ -1,10 +1,9 @@
package mocks
import (
"github.com/deluan/gosonic/models"
"github.com/deluan/gosonic/domain"
"fmt"
"encoding/json"
"github.com/deluan/gosonic/repositories"
"errors"
)
@ -13,8 +12,8 @@ func CreateMockArtistIndexRepo() *MockArtistIndex {
}
type MockArtistIndex struct {
repositories.ArtistIndex
data []models.ArtistIndex
domain.ArtistIndexRepository
data []domain.ArtistIndex
err bool
}
@ -23,14 +22,14 @@ func (m *MockArtistIndex) SetError(err bool) {
}
func (m *MockArtistIndex) SetData(j string, length int) {
m.data = make([]models.ArtistIndex, length)
m.data = make([]domain.ArtistIndex, length)
err := json.Unmarshal([]byte(j), &m.data)
if err != nil {
fmt.Println("ERROR: ", err)
}
}
func (m *MockArtistIndex) GetAll() ([]models.ArtistIndex, error) {
func (m *MockArtistIndex) GetAll() ([]domain.ArtistIndex, error) {
if m.err {
return nil, errors.New("Error!")
}

View File

@ -1,8 +1,8 @@
package mocks
import (
"github.com/deluan/gosonic/repositories"
"errors"
"github.com/deluan/gosonic/domain"
)
func CreateMockPropertyRepo() *MockProperty {
@ -10,7 +10,7 @@ func CreateMockPropertyRepo() *MockProperty {
}
type MockProperty struct {
repositories.Property
domain.PropertyRepository
data map[string]string
err bool
}