/
page.go
94 lines (80 loc) · 2.29 KB
/
page.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package hal
import (
"net/url"
"strconv"
sUrl "github.com/AnneNamuli/go-stellar/support/url"
)
// BasePage represents the simplest page: one with no links and only embedded records.
// Can be used to build custom page-like resources
type BasePage struct {
FullURL *url.URL `json:"-"`
Embedded struct {
Records []Pageable `json:"records"`
} `json:"_embedded"`
}
// Add appends the provided record onto the page
func (p *BasePage) Add(rec Pageable) {
p.Embedded.Records = append(p.Embedded.Records, rec)
}
// Init initialized the Records slice. This ensures that an empty page
// renders its records as an empty array, rather than `null`
func (p *BasePage) Init() {
if p.Embedded.Records == nil {
p.Embedded.Records = make([]Pageable, 0, 1)
}
}
// Links represents the Links in a Page
type Links struct {
Self Link `json:"self"`
Next Link `json:"next"`
Prev Link `json:"prev"`
}
// Page represents the common page configuration (i.e. has self, next, and prev
// links) and has a helper method `PopulateLinks` to automate their
// initialization.
type Page struct {
Links Links `json:"_links"`
BasePage
Order string `json:"-"`
Limit uint64 `json:"-"`
Cursor string `json:"-"`
}
// PopulateLinks sets the common links for a page.
func (p *Page) PopulateLinks() {
p.Init()
rec := p.Embedded.Records
//verify paging params
var selfUrl sUrl.URL
if p.FullURL != nil {
selfUrl = sUrl.URL(*p.FullURL).
SetParam("cursor", p.Cursor).
SetParam("order", p.Order).
SetParam("limit", strconv.FormatInt(int64(p.Limit), 10))
}
//self: re-encode existing query params
p.Links.Self = NewLink(selfUrl.String())
//next: update cursor to last record (if any)
nextUrl := selfUrl
if len(rec) > 0 {
nextUrl = nextUrl.SetParam("cursor", rec[len(rec)-1].PagingToken())
}
p.Links.Next = NewLink(nextUrl.String())
//prev: inverse order and update cursor to first record (if any)
prevUrl := selfUrl.SetParam("order", p.InvertedOrder())
if len(rec) > 0 {
prevUrl = prevUrl.SetParam("cursor", rec[0].PagingToken())
}
p.Links.Prev = NewLink(prevUrl.String())
}
// InvertedOrder returns the inversion of the page's current order. Used to
// populate the prev link
func (p *Page) InvertedOrder() string {
switch p.Order {
case "asc":
return "desc"
case "desc":
return "asc"
default:
return "asc"
}
}