115 lines
2.6 KiB
Go
115 lines
2.6 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func Any() Selector {
|
|
return func(r Record) bool { return true }
|
|
}
|
|
|
|
func And(a, b Selector) Selector {
|
|
return func(r Record) bool {
|
|
return a(r) && b(r)
|
|
}
|
|
}
|
|
|
|
func OnlyNature(n Nature) Selector {
|
|
return func(r Record) bool {
|
|
return r.Nature() == n
|
|
}
|
|
}
|
|
|
|
func OnlyAssetCountry(c int64) Selector {
|
|
return func(r Record) bool {
|
|
return r.AssetCountry() == c
|
|
}
|
|
}
|
|
|
|
// selectorParser is a function that parses a selector value string into a Selector
|
|
type selectorParser func(string) (Selector, error)
|
|
|
|
// parsers maps selector keys to their parser functions
|
|
var parsers = map[string]selectorParser{
|
|
"code": parseNature,
|
|
"assetCountry": parseAssetCountry,
|
|
}
|
|
|
|
func parseNature(value string) (Selector, error) {
|
|
if value == "" {
|
|
return nil, fmt.Errorf("code selector requires a non-empty value")
|
|
}
|
|
nature := Nature(value)
|
|
if !nature.Valid() {
|
|
return nil, fmt.Errorf("invalid nature code %q", value)
|
|
}
|
|
return OnlyNature(nature), nil
|
|
}
|
|
|
|
func parseAssetCountry(value string) (Selector, error) {
|
|
if value == "" {
|
|
return nil, fmt.Errorf("assetCountry selector requires a non-empty value")
|
|
}
|
|
i, err := strconv.ParseInt(value, 10, 64)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("assetCountry value must be a valid integer: %w", err)
|
|
}
|
|
return OnlyAssetCountry(i), nil
|
|
}
|
|
|
|
// ParseSelectors parses a list of selector strings into a composed Selector.
|
|
// Each selector string must be in the format "key:value" where key is one of:
|
|
// - code: filter by nature (e.g., "code:G01")
|
|
// - assetCountry: filter by asset country code (e.g., "assetCountry:840")
|
|
//
|
|
// Multiple selectors are combined with AND logic.
|
|
// If no selectors are provided, returns Any() which matches all records.
|
|
func ParseSelectors(sl []string) (Selector, error) {
|
|
if len(sl) == 0 {
|
|
return Any(), nil
|
|
}
|
|
|
|
// Parse the first selector
|
|
first, err := parseSingleSelector(sl[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// If there's only one, return it
|
|
if len(sl) == 1 {
|
|
return first, nil
|
|
}
|
|
|
|
// Recursively parse the rest and combine with AND
|
|
rest, err := ParseSelectors(sl[1:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return And(first, rest), nil
|
|
}
|
|
|
|
func parseSingleSelector(s string) (Selector, error) {
|
|
key, value, found := strings.Cut(s, ":")
|
|
if !found {
|
|
return nil, fmt.Errorf("invalid selector format %q: must be 'key:value'", s)
|
|
}
|
|
|
|
parser, ok := parsers[key]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unknown selector key %q: supported keys are %v", key, supportedKeys())
|
|
}
|
|
|
|
return parser(value)
|
|
}
|
|
|
|
func supportedKeys() []string {
|
|
keys := make([]string, 0, len(parsers))
|
|
for k := range parsers {
|
|
keys = append(keys, k)
|
|
}
|
|
return keys
|
|
}
|