core/internal/domain/version.go

311 lines
5.6 KiB
Go

package domain
import (
"encoding/base64"
"net/url"
)
const (
versionCodeMinLength = 2
versionCodeMaxLength = 2
)
type Version struct {
code string
name string
host string
timezone string
}
var versionModelName = "Version"
// UnmarshalVersionFromDatabase unmarshals Version from the database.
//
// It should be used only for unmarshalling from the database!
// You can't use UnmarshalVersionFromDatabase as constructor - It may put domain into the invalid state!
func UnmarshalVersionFromDatabase(
code string,
name string,
host string,
timezone string,
) (Version, error) {
if code == "" {
return Version{}, ValidationError{
Model: versionModelName,
Field: "code",
Err: ErrRequired,
}
}
if name == "" {
return Version{}, ValidationError{
Model: versionModelName,
Field: "name",
Err: ErrRequired,
}
}
if host == "" {
return Version{}, ValidationError{
Model: versionModelName,
Field: "host",
Err: ErrRequired,
}
}
if timezone == "" {
return Version{}, ValidationError{
Model: versionModelName,
Field: "timezone",
Err: ErrRequired,
}
}
return Version{
code: code,
name: name,
host: host,
timezone: timezone,
}, nil
}
func (v Version) Code() string {
return v.code
}
func (v Version) Name() string {
return v.name
}
func (v Version) Host() string {
return v.host
}
func (v Version) Timezone() string {
return v.timezone
}
func (v Version) URL() *url.URL {
return &url.URL{
Scheme: "https",
Host: v.host,
}
}
func (v Version) IsZero() bool {
return v == Version{}
}
type Versions []Version
type VersionSort uint8
const (
VersionSortCodeASC VersionSort = iota + 1
VersionSortCodeDESC
)
type VersionCursor struct {
code NullString
}
const versionCursorModelName = "VersionCursor"
func NewVersionCursor(code NullString) (VersionCursor, error) {
if !code.Valid {
return VersionCursor{}, nil
}
if err := validateVersionCode(code.Value); err != nil {
return VersionCursor{}, ValidationError{
Model: versionCursorModelName,
Field: "code",
Err: err,
}
}
return VersionCursor{
code: code,
}, nil
}
const (
encodedVersionCursorMinLength = 1
encodedVersionCursorMaxLength = 1000
)
func decodeVersionCursor(encoded string) (VersionCursor, error) {
if err := validateStringLen(encoded, encodedVersionCursorMinLength, encodedVersionCursorMaxLength); err != nil {
return VersionCursor{}, err
}
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return VersionCursor{}, ErrInvalidCursor
}
vc, err := NewVersionCursor(NullString{
Value: string(decoded),
Valid: true,
})
if err != nil {
return VersionCursor{}, ErrInvalidCursor
}
return vc, nil
}
func (vc VersionCursor) Code() NullString {
return vc.code
}
func (vc VersionCursor) IsZero() bool {
return !vc.code.Valid
}
func (vc VersionCursor) Encode() string {
if vc.IsZero() {
return ""
}
return base64.StdEncoding.EncodeToString([]byte(vc.code.Value))
}
type ListVersionsParams struct {
sort []VersionSort
cursor VersionCursor
limit int
}
const (
VersionListMaxLimit = 200
listVersionsParamsModelName = "ListVersionsParams"
)
func NewListVersionsParams() ListVersionsParams {
return ListVersionsParams{
sort: []VersionSort{VersionSortCodeASC},
limit: VersionListMaxLimit,
}
}
const (
versionSortMinLength = 1
versionSortMaxLength = 1
)
func (params *ListVersionsParams) Sort() []VersionSort {
return params.sort
}
func (params *ListVersionsParams) SetSort(sort []VersionSort) error {
if err := validateSliceLen(sort, versionSortMinLength, versionSortMaxLength); err != nil {
return ValidationError{
Model: listVersionsParamsModelName,
Field: "sort",
Err: err,
}
}
params.sort = sort
return nil
}
func (params *ListVersionsParams) Cursor() VersionCursor {
return params.cursor
}
func (params *ListVersionsParams) SetCursor(vc VersionCursor) error {
params.cursor = vc
return nil
}
func (params *ListVersionsParams) SetEncodedCursor(encoded string) error {
decoded, err := decodeVersionCursor(encoded)
if err != nil {
return ValidationError{
Model: listVersionsParamsModelName,
Field: "cursor",
Err: err,
}
}
params.cursor = decoded
return nil
}
func (params *ListVersionsParams) Limit() int {
return params.limit
}
func (params *ListVersionsParams) SetLimit(limit int) error {
if err := validateIntInRange(limit, 1, VersionListMaxLimit); err != nil {
return ValidationError{
Model: listVersionsParamsModelName,
Field: "limit",
Err: err,
}
}
params.limit = limit
return nil
}
type ListVersionsResult struct {
versions Versions
self VersionCursor
next VersionCursor
}
const listVersionsResultModelName = "ListVersionsResult"
func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult, error) {
var err error
res := ListVersionsResult{
versions: versions,
}
if len(versions) > 0 {
res.self, err = NewVersionCursor(NullString{
Value: versions[0].Code(),
Valid: true,
})
if err != nil {
return ListVersionsResult{}, ValidationError{
Model: listVersionsResultModelName,
Field: "self",
Err: err,
}
}
}
res.next, err = NewVersionCursor(NullString{
Value: next.Code(),
Valid: !next.IsZero(),
})
if err != nil {
return ListVersionsResult{}, ValidationError{
Model: listVersionsResultModelName,
Field: "next",
Err: err,
}
}
return res, nil
}
func (res ListVersionsResult) Versions() Versions {
return res.versions
}
func (res ListVersionsResult) Self() VersionCursor {
return res.self
}
func (res ListVersionsResult) Next() VersionCursor {
return res.next
}