view pkg/models/common.go @ 2025:070ac9dd61a1 unify_imports

Bring manual imports to new import modeling.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 24 Jan 2019 18:19:43 +0100
parents 0bc0312105e4
children ae0021feaac8
line wrap: on
line source

// This is Free Software under GNU Affero General Public License v >= 3.0
// without warranty, see README.md and license for details.
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// License-Filename: LICENSES/AGPL-3.0.txt
//
// Copyright (C) 2018 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>

package models

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"
)

var (
	errNoString    = errors.New("Not a string")
	errNoByteSlice = errors.New("Not a byte slice")
)

// WGS84 is the EPSG of the World Geodetic System 1984.
const WGS84 = 4326

const DateFormat = "2006-01-02"

type (
	Date struct{ time.Time }
	// Country is a valid country 2 letter code.
	Country string
	// UniqueCountries is a list of unique countries.
	UniqueCountries []Country
)

func (srd Date) MarshalJSON() ([]byte, error) {
	return json.Marshal(srd.Format(DateFormat))
}

func (srd *Date) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	d, err := time.Parse(DateFormat, s)
	if err == nil {
		*srd = Date{d}
	}
	return err
}

var (
	validCountries = []string{
		"AT", "BG", "DE", "HU", "HR",
		"MD", "RO", "RS", "SK", "UA",
	}
)

// UnmarshalJSON ensures that the given string forms a valid
// two letter country code.
func (c *Country) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	u := strings.ToUpper(s)
	for _, v := range validCountries {
		if v == u {
			*c = Country(v)
			return nil
		}
	}
	return fmt.Errorf("'%s' is not a valid country", s)
}

// Value implements the driver.Valuer interface.
func (c Country) Value() (driver.Value, error) {
	return string(c), nil
}

// Scan implements the sql.Scanner interfaces.
func (c *Country) Scan(src interface{}) (err error) {
	if s, ok := src.(string); ok {
		*c = Country(s)
	} else {
		err = errNoString
	}
	return
}

func (uc *UniqueCountries) UnmarshalJSON(data []byte) error {
	var countries []Country
	if err := json.Unmarshal(data, &countries); err != nil {
		return err
	}
	unique := map[Country]struct{}{}
	for _, c := range countries {
		if _, found := unique[c]; found {
			return fmt.Errorf("country '%s' is not unique", string(c))
		}
		unique[c] = struct{}{}
	}
	*uc = countries
	return nil
}