2021-02-09 14:44:55 +00:00
|
|
|
package locode
|
|
|
|
|
|
|
|
import (
|
2021-05-18 08:12:51 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
|
2021-02-09 14:44:55 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/util/locode"
|
2021-11-10 07:08:33 +00:00
|
|
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
2021-02-09 14:44:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var errMissingRequiredAttr = errors.New("missing required attribute in DB record")
|
|
|
|
|
2021-02-10 10:13:42 +00:00
|
|
|
// VerifyAndUpdate validates UN-LOCODE attribute of n
|
2021-02-09 14:44:55 +00:00
|
|
|
// and adds a group of related attributes.
|
|
|
|
//
|
2021-06-09 10:47:12 +00:00
|
|
|
// If n contains at least one of the LOCODE-derived attributes,
|
|
|
|
// an error returns.
|
|
|
|
//
|
|
|
|
// If n contains UN-LOCODE attribute and its value does not
|
2021-02-09 14:44:55 +00:00
|
|
|
// match the UN/LOCODE format, an error returns.
|
|
|
|
//
|
|
|
|
// New attributes are formed from the record of DB instance (Prm).
|
|
|
|
// If DB entry R was found w/o errors, then new attributes are:
|
|
|
|
// * CountryCode: R.CountryCode().String();
|
|
|
|
// * Country: R.CountryName();
|
2021-02-10 10:28:14 +00:00
|
|
|
// * Location: Record.LocationName();
|
2021-02-09 14:44:55 +00:00
|
|
|
// * SubDivCode: R.SubDivCode();
|
|
|
|
// * SubDiv: R.SubDivName();
|
|
|
|
// * Continent: R.Continent().String().
|
|
|
|
//
|
2021-02-10 10:13:42 +00:00
|
|
|
// UN-LOCODE attribute remains untouched.
|
2021-02-09 14:44:55 +00:00
|
|
|
func (v *Validator) VerifyAndUpdate(n *netmap.NodeInfo) error {
|
|
|
|
mAttr := uniqueAttributes(n.Attributes())
|
|
|
|
|
2021-06-09 10:47:12 +00:00
|
|
|
// check if derived attributes are presented
|
|
|
|
for attrKey := range v.mAttr {
|
|
|
|
if _, ok := mAttr[attrKey]; ok {
|
|
|
|
return fmt.Errorf("attribute derived from %s is presented: %s",
|
|
|
|
netmap.AttrUNLOCODE,
|
|
|
|
attrKey,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 20:54:27 +00:00
|
|
|
attrLocode, ok := mAttr[netmap.AttrUNLOCODE]
|
2021-02-09 14:44:55 +00:00
|
|
|
if !ok {
|
2021-02-24 18:18:36 +00:00
|
|
|
return nil
|
2021-02-09 14:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lc, err := locode.FromString(attrLocode.Value())
|
|
|
|
if err != nil {
|
2021-05-18 08:12:51 +00:00
|
|
|
return fmt.Errorf("invalid locode value: %w", err)
|
2021-02-09 14:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
record, err := v.db.Get(lc)
|
|
|
|
if err != nil {
|
2021-05-18 08:12:51 +00:00
|
|
|
return fmt.Errorf("could not get locode record from DB: %w", err)
|
2021-02-09 14:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for attrKey, attrDesc := range v.mAttr {
|
|
|
|
attrVal := attrDesc.converter(record)
|
|
|
|
if attrVal == "" {
|
|
|
|
if !attrDesc.optional {
|
|
|
|
return errMissingRequiredAttr
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-03-15 11:39:53 +00:00
|
|
|
var a netmap.NodeAttribute
|
2021-02-09 14:44:55 +00:00
|
|
|
a.SetKey(attrKey)
|
|
|
|
a.SetValue(attrVal)
|
|
|
|
|
|
|
|
mAttr[attrKey] = a
|
|
|
|
}
|
|
|
|
|
|
|
|
as := n.Attributes()
|
|
|
|
as = as[:0]
|
|
|
|
|
|
|
|
for _, attr := range mAttr {
|
|
|
|
as = append(as, attr)
|
|
|
|
}
|
|
|
|
|
|
|
|
n.SetAttributes(as...)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-03-15 11:39:53 +00:00
|
|
|
func uniqueAttributes(as []netmap.NodeAttribute) map[string]netmap.NodeAttribute {
|
|
|
|
mAttr := make(map[string]netmap.NodeAttribute, len(as))
|
2021-02-09 14:44:55 +00:00
|
|
|
|
|
|
|
for _, attr := range as {
|
|
|
|
mAttr[attr.Key()] = attr
|
|
|
|
}
|
|
|
|
|
|
|
|
return mAttr
|
|
|
|
}
|