github.com/eris-ltd/erisdb@v0.25.0/event/query/tags.go (about) 1 package query 2 3 import ( 4 "sort" 5 "strings" 6 ) 7 8 type Tagged interface { 9 Keys() []string 10 Get(key string) (value string, ok bool) 11 // Len returns the number of tags. 12 Len() int 13 } 14 15 type TagMap map[string]interface{} 16 17 func MapFromTagged(tagged Tagged) map[string]interface{} { 18 tags := make(map[string]interface{}) 19 for _, k := range tagged.Keys() { 20 v, ok := tagged.Get(k) 21 if ok { 22 tags[k] = v 23 } 24 } 25 return tags 26 } 27 28 func (ts TagMap) Get(key string) (value string, ok bool) { 29 var vint interface{} 30 vint, ok = ts[key] 31 if !ok { 32 return "", false 33 } 34 return StringFromValue(vint), true 35 } 36 37 func (ts TagMap) Len() int { 38 return len(ts) 39 } 40 41 func (ts TagMap) Map() map[string]interface{} { 42 return ts 43 } 44 45 func (ts TagMap) Keys() []string { 46 keys := make([]string, 0, len(ts)) 47 for k := range ts { 48 keys = append(keys, k) 49 } 50 sort.Strings(keys) 51 return keys 52 } 53 54 type CombinedTags struct { 55 keys []string 56 ks map[string][]Tagged 57 concat bool 58 } 59 60 func NewCombinedTags() *CombinedTags { 61 return &CombinedTags{ 62 ks: make(map[string][]Tagged), 63 } 64 } 65 66 func MergeTags(tags ...Tagged) *CombinedTags { 67 ct := NewCombinedTags() 68 ct.AddTags(false, tags...) 69 return ct 70 } 71 72 func ConcatTags(tags ...Tagged) *CombinedTags { 73 ct := NewCombinedTags() 74 ct.AddTags(true, tags...) 75 return ct 76 } 77 78 // Adds each of tagsList to CombinedTags - choosing whether values for the same key should 79 // be concatenated or whether the first should value should stick 80 func (ct *CombinedTags) AddTags(concat bool, tagsList ...Tagged) { 81 for _, t := range tagsList { 82 for _, k := range t.Keys() { 83 if len(ct.ks[k]) == 0 { 84 ct.keys = append(ct.keys, k) 85 // Store reference to key-holder amongst Taggeds 86 ct.ks[k] = append(ct.ks[k], t) 87 } else if concat { 88 // Store additional tag reference only if concat, otherwise first key-holder wins 89 ct.ks[k] = append(ct.ks[k], t) 90 } 91 } 92 } 93 } 94 95 func (ct *CombinedTags) Get(key string) (string, bool) { 96 ts := ct.ks[key] 97 if len(ts) == 0 { 98 return "", false 99 } 100 values := make([]string, 0, len(ts)) 101 for _, t := range ts { 102 value, ok := t.Get(key) 103 if ok { 104 values = append(values, value) 105 } 106 } 107 if len(values) == 0 { 108 return "", false 109 } 110 return strings.Join(values, MultipleValueTagSeparator), true 111 } 112 113 func (ct *CombinedTags) Len() (length int) { 114 return len(ct.keys) 115 } 116 117 func (ct *CombinedTags) Keys() []string { 118 return ct.keys 119 }