155 lines
3.7 KiB
Go
155 lines
3.7 KiB
Go
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)
|
|
}
|
|
|
|
if ok, httpErr := car.Verify(); !ok {
|
|
return &Response{}, httpErr
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
if ok, httpErr := car.Verify(); !ok {
|
|
return &Response{}, httpErr
|
|
}
|
|
|
|
err := s.CarStorage.Update(car)
|
|
return &Response{Code: http.StatusOK}, err
|
|
}
|