diff options
Diffstat (limited to 'common/maps/params.go')
-rw-r--r-- | common/maps/params.go | 109 |
1 files changed, 61 insertions, 48 deletions
diff --git a/common/maps/params.go b/common/maps/params.go index 2d62ad752..ecb63d7a5 100644 --- a/common/maps/params.go +++ b/common/maps/params.go @@ -19,76 +19,89 @@ import ( "github.com/spf13/cast" ) +// Params is a map where all keys are lower case. +type Params map[string]interface{} + +// Get does a lower case and nested search in this map. +// It will return nil if none found. +func (p Params) Get(indices ...string) interface{} { + v, _, _ := getNested(p, indices) + return v +} + +func getNested(m map[string]interface{}, indices []string) (interface{}, string, map[string]interface{}) { + if len(indices) == 0 { + return nil, "", nil + } + + first := indices[0] + v, found := m[strings.ToLower(cast.ToString(first))] + if !found { + return nil, "", nil + } + + if len(indices) == 1 { + return v, first, m + } + + switch m2 := v.(type) { + case Params: + return getNested(m2, indices[1:]) + case map[string]interface{}: + return getNested(m2, indices[1:]) + default: + return nil, "", nil + } +} + // GetNestedParam gets the first match of the keyStr in the candidates given. // It will first try the exact match and then try to find it as a nested map value, // using the given separator, e.g. "mymap.name". // It assumes that all the maps given have lower cased keys. -func GetNestedParam(keyStr, separator string, candidates ...map[string]interface{}) (interface{}, error) { +func GetNestedParam(keyStr, separator string, candidates ...Params) (interface{}, error) { keyStr = strings.ToLower(keyStr) - lookupFn := func(key string) interface{} { - for _, m := range candidates { - if v, ok := m[key]; ok { - return v - } + // Try exact match first + for _, m := range candidates { + if v, ok := m[keyStr]; ok { + return v, nil } - - return nil - } - - v, _, _, err := GetNestedParamFn(keyStr, separator, lookupFn) - return v, err -} - -func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) { - result, _ := traverseDirectParams(keyStr, lookupFn) - if result != nil { - return result, keyStr, nil, nil } keySegments := strings.Split(keyStr, separator) - if len(keySegments) == 1 { - return nil, keyStr, nil, nil + for _, m := range candidates { + if v := m.Get(keySegments...); v != nil { + return v, nil + } } - return traverseNestedParams(keySegments, lookupFn) -} + return nil, nil -func traverseDirectParams(keyStr string, lookupFn func(key string) interface{}) (interface{}, error) { - return lookupFn(keyStr), nil } -func traverseNestedParams(keySegments []string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) { - firstKey, rest := keySegments[0], keySegments[1:] - result := lookupFn(firstKey) - if result == nil || len(rest) == 0 { - return result, firstKey, nil, nil +func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) { + keySegments := strings.Split(strings.ToLower(keyStr), separator) + if len(keySegments) == 0 { + return nil, "", nil, nil } - switch m := result.(type) { - case map[string]interface{}: - v, key, owner := traverseParams(rest, m) - return v, key, owner, nil - default: + first := lookupFn(keySegments[0]) + if first == nil { return nil, "", nil, nil } -} - -func traverseParams(keys []string, m map[string]interface{}) (interface{}, string, map[string]interface{}) { - // Shift first element off. - firstKey, rest := keys[0], keys[1:] - result := m[firstKey] - // No point in continuing here. - if result == nil { - return result, "", nil + if len(keySegments) == 1 { + return first, keySegments[0], nil, nil } - if len(rest) == 0 { - // That was the last key. - return result, firstKey, m + switch m := first.(type) { + case map[string]interface{}: + v, key, owner := getNested(m, keySegments[1:]) + return v, key, owner, nil + case Params: + v, key, owner := getNested(m, keySegments[1:]) + return v, key, owner, nil } - // That was not the last key. - return traverseParams(rest, cast.ToStringMap(result)) + return nil, "", nil, nil } |