map_utils.go raw

   1  package javaproperties
   2  
   3  import (
   4  	"strings"
   5  
   6  	"github.com/spf13/cast"
   7  )
   8  
   9  // THIS CODE IS COPIED HERE: IT SHOULD NOT BE MODIFIED
  10  // AT SOME POINT IT WILL BE MOVED TO A COMMON PLACE
  11  // deepSearch scans deep maps, following the key indexes listed in the
  12  // sequence "path".
  13  // The last value is expected to be another map, and is returned.
  14  //
  15  // In case intermediate keys do not exist, or map to a non-map value,
  16  // a new map is created and inserted, and the search continues from there:
  17  // the initial map "m" may be modified!
  18  func deepSearch(m map[string]any, path []string) map[string]any {
  19  	for _, k := range path {
  20  		m2, ok := m[k]
  21  		if !ok {
  22  			// intermediate key does not exist
  23  			// => create it and continue from there
  24  			m3 := make(map[string]any)
  25  			m[k] = m3
  26  			m = m3
  27  			continue
  28  		}
  29  		m3, ok := m2.(map[string]any)
  30  		if !ok {
  31  			// intermediate key is a value
  32  			// => replace with a new map
  33  			m3 = make(map[string]any)
  34  			m[k] = m3
  35  		}
  36  		// continue search from here
  37  		m = m3
  38  	}
  39  	return m
  40  }
  41  
  42  // flattenAndMergeMap recursively flattens the given map into a new map
  43  // Code is based on the function with the same name in the main package.
  44  // TODO: move it to a common place.
  45  func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
  46  	if shadow != nil && prefix != "" && shadow[prefix] != nil {
  47  		// prefix is shadowed => nothing more to flatten
  48  		return shadow
  49  	}
  50  	if shadow == nil {
  51  		shadow = make(map[string]any)
  52  	}
  53  
  54  	var m2 map[string]any
  55  	if prefix != "" {
  56  		prefix += delimiter
  57  	}
  58  	for k, val := range m {
  59  		fullKey := prefix + k
  60  		switch val := val.(type) {
  61  		case map[string]any:
  62  			m2 = val
  63  		case map[any]any:
  64  			m2 = cast.ToStringMap(val)
  65  		default:
  66  			// immediate value
  67  			shadow[strings.ToLower(fullKey)] = val
  68  			continue
  69  		}
  70  		// recursively merge to shadow map
  71  		shadow = flattenAndMergeMap(shadow, m2, fullKey, delimiter)
  72  	}
  73  	return shadow
  74  }
  75