github.com/sleungcy-sap/cli@v7.1.0+incompatible/util/generic/map.go (about) 1 package generic 2 3 import ( 4 "fmt" 5 "reflect" 6 ) 7 8 type Map interface { 9 IsEmpty() bool 10 Count() int 11 Keys() []interface{} 12 Has(key interface{}) bool 13 Except(keys []interface{}) Map 14 IsNil(key interface{}) bool 15 NotNil(key interface{}) bool 16 Get(key interface{}) interface{} 17 Set(key interface{}, value interface{}) 18 Delete(key interface{}) 19 String() string 20 } 21 22 func NewMap(data ...interface{}) Map { 23 if len(data) == 0 { 24 return newEmptyMap() 25 } else if len(data) > 1 { 26 panic("NewMap called with more than one argument") 27 } 28 29 switch data := data[0].(type) { 30 case nil: 31 return newEmptyMap() 32 case Map: 33 return data 34 case map[string]string: 35 stringMap := newEmptyMap() 36 for key, val := range data { 37 stringMap.Set(key, val) 38 } 39 return stringMap 40 case map[string]interface{}: 41 stringToInterfaceMap := newEmptyMap() 42 for key, val := range data { 43 stringToInterfaceMap.Set(key, val) 44 } 45 return stringToInterfaceMap 46 case map[interface{}]interface{}: 47 mapp := ConcreteMap(data) 48 return &mapp 49 } 50 51 fmt.Printf("\n\n map: %T", data) 52 panic("NewMap called with unexpected argument") 53 } 54 55 type Iterator func(key, val interface{}) 56 57 func newEmptyMap() Map { 58 return &ConcreteMap{} 59 } 60 61 type ConcreteMap map[interface{}]interface{} 62 63 func (data *ConcreteMap) Count() int { 64 return len(*data) 65 } 66 67 func (data *ConcreteMap) Delete(key interface{}) { 68 delete(*data, key) 69 } 70 71 func (data *ConcreteMap) Except(keys []interface{}) Map { 72 otherMap := NewMap() 73 Each(data, func(key, value interface{}) { 74 if !Contains(keys, key) { 75 otherMap.Set(key, value) 76 } 77 }) 78 return otherMap 79 } 80 81 func (data *ConcreteMap) Get(key interface{}) interface{} { 82 return (*data)[key] 83 } 84 85 func (data *ConcreteMap) Has(key interface{}) bool { 86 _, ok := (*data)[key] 87 return ok 88 } 89 90 func (data *ConcreteMap) IsEmpty() bool { 91 return data.Count() == 0 92 } 93 94 func (data *ConcreteMap) IsNil(key interface{}) bool { 95 maybe, ok := (*data)[key] 96 return ok && maybe == nil 97 } 98 99 func (data *ConcreteMap) Keys() (keys []interface{}) { 100 keys = make([]interface{}, 0, data.Count()) 101 for key := range *data { 102 keys = append(keys, key) 103 } 104 105 return 106 } 107 108 func (data *ConcreteMap) NotNil(key interface{}) bool { 109 maybe, ok := (*data)[key] 110 return ok && maybe != nil 111 } 112 113 func (data *ConcreteMap) Set(key, value interface{}) { 114 (*data)[key] = value 115 } 116 117 func (data *ConcreteMap) String() string { 118 return fmt.Sprintf("% v", *data) 119 } 120 121 func Contains(collection, item interface{}) bool { 122 switch collection := collection.(type) { 123 case Map: 124 return collection.Has(item) 125 case []interface{}: 126 for _, val := range collection { 127 if val == item { 128 return true 129 } 130 } 131 return false 132 } 133 134 panic("unexpected type passed to Contains") 135 } 136 137 func Each(collection Map, cb Iterator) { 138 for _, key := range collection.Keys() { 139 cb(key, collection.Get(key)) 140 } 141 } 142 143 func IsMappable(value interface{}) bool { 144 if value == nil { 145 return false 146 } 147 switch value.(type) { 148 case Map: 149 return true 150 default: 151 return reflect.TypeOf(value).Kind() == reflect.Map 152 } 153 }