go-jsonapi-example/internal/resource/resource_car.go

155 lines
3.7 KiB
Go
Raw Normal View History

2021-03-18 18:52:41 +00:00
package resource
import (
"errors"
"net/http"
"sort"
"strconv"
"go-jsonapi-example/internal/model"
"go-jsonapi-example/internal/storage"
"github.com/manyminds/api2go"
)
// CarResource for api2go routes
type CarResource struct {
CarStorage *storage.CarStorage
}
// FindAll to satisfy api2go data source interface
func (s CarResource) FindAll(r api2go.Request) (api2go.Responder, error) {
var result []model.Car
cars := s.CarStorage.GetAll()
for _, car := range cars {
result = append(result, *car)
}
return &Response{Res: result}, nil
}
// PaginatedFindAll can be used to load cars in chunks
func (s CarResource) PaginatedFindAll(r api2go.Request) (uint, api2go.Responder, error) {
var (
result []model.Car
number, size, offset, limit string
keys []int
)
cars := s.CarStorage.GetAll()
for k := range cars {
i, err := strconv.ParseInt(k, 10, 64)
if err != nil {
return 0, &Response{}, err
}
keys = append(keys, int(i))
}
sort.Ints(keys)
numberQuery, ok := r.QueryParams["page[number]"]
if ok {
number = numberQuery[0]
}
sizeQuery, ok := r.QueryParams["page[size]"]
if ok {
size = sizeQuery[0]
}
offsetQuery, ok := r.QueryParams["page[offset]"]
if ok {
offset = offsetQuery[0]
}
limitQuery, ok := r.QueryParams["page[limit]"]
if ok {
limit = limitQuery[0]
}
if size != "" {
sizeI, err := strconv.ParseUint(size, 10, 64)
if err != nil {
return 0, &Response{}, err
}
numberI, err := strconv.ParseUint(number, 10, 64)
if err != nil {
return 0, &Response{}, err
}
start := sizeI * (numberI - 1)
for i := start; i < start+sizeI; i++ {
if i >= uint64(len(cars)) {
break
}
result = append(result, *cars[strconv.FormatInt(int64(keys[i]), 10)])
}
} else {
limitI, err := strconv.ParseUint(limit, 10, 64)
if err != nil {
return 0, &Response{}, err
}
offsetI, err := strconv.ParseUint(offset, 10, 64)
if err != nil {
return 0, &Response{}, err
}
for i := offsetI; i < offsetI+limitI; i++ {
if i >= uint64(len(cars)) {
break
}
result = append(result, *cars[strconv.FormatInt(int64(keys[i]), 10)])
}
}
return uint(len(cars)), &Response{Res: result}, nil
}
// FindOne to satisfy `api2go.DataSource` interface
// this method should return the car with the given ID, otherwise an error
func (s CarResource) FindOne(ID string, r api2go.Request) (api2go.Responder, error) {
car, err := s.CarStorage.GetOne(ID)
if err != nil {
return &Response{}, api2go.NewHTTPError(err, err.Error(), http.StatusNotFound)
}
return &Response{Res: car}, nil
}
// Create method to satisfy `api2go.DataSource` interface
func (s CarResource) Create(obj interface{}, r api2go.Request) (api2go.Responder, error) {
car, ok := obj.(model.Car)
if !ok {
return &Response{}, api2go.NewHTTPError(errors.New("Invalid instance given"), "Invalid instance given", http.StatusBadRequest)
}
2021-03-19 17:24:02 +00:00
if ok, httpErr := car.Verify(); !ok {
return &Response{}, httpErr
}
2021-03-18 18:52:41 +00:00
id := s.CarStorage.Insert(car)
car.ID = id
return &Response{Res: car, Code: http.StatusCreated}, nil
}
// Delete to satisfy `api2go.DataSource` interface
func (s CarResource) Delete(id string, r api2go.Request) (api2go.Responder, error) {
err := s.CarStorage.Delete(id)
return &Response{Code: http.StatusNoContent}, err
}
//Update stores all changes on the car
func (s CarResource) Update(obj interface{}, r api2go.Request) (api2go.Responder, error) {
car, ok := obj.(model.Car)
if !ok {
return &Response{}, api2go.NewHTTPError(errors.New("Invalid instance given"), "Invalid instance given", http.StatusBadRequest)
}
2021-03-19 17:24:02 +00:00
if ok, httpErr := car.Verify(); !ok {
return &Response{}, httpErr
}
2021-03-18 18:52:41 +00:00
err := s.CarStorage.Update(car)
2021-03-19 17:24:02 +00:00
return &Response{Code: http.StatusOK}, err
2021-03-18 18:52:41 +00:00
}