github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/thirdparty/eventlog/metadata.go (about) 1 package eventlog 2 3 import ( 4 "encoding/json" 5 "errors" 6 "reflect" 7 8 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/satori/go.uuid" 9 ) 10 11 // Metadata is a convenience type for generic maps 12 type Metadata map[string]interface{} 13 14 // Uuid returns a Metadata with the string key and UUID value 15 func Uuid(key string) Metadata { 16 return Metadata{ 17 key: uuid.NewV4().String(), 18 } 19 } 20 21 // DeepMerge merges the second Metadata parameter into the first. 22 // Nested Metadata are merged recursively. Primitives are over-written. 23 func DeepMerge(b, a Metadata) Metadata { 24 out := Metadata{} 25 for k, v := range b { 26 out[k] = v 27 } 28 for k, v := range a { 29 30 maybe, err := Metadatify(v) 31 if err != nil { 32 // if the new value is not meta. just overwrite the dest vaue 33 out[k] = v 34 continue 35 } 36 37 // it is meta. What about dest? 38 outv, exists := out[k] 39 if !exists { 40 // the new value is meta, but there's no dest value. just write it 41 out[k] = v 42 continue 43 } 44 45 outMetadataValue, err := Metadatify(outv) 46 if err != nil { 47 // the new value is meta and there's a dest value, but the dest 48 // value isn't meta. just overwrite 49 out[k] = v 50 continue 51 } 52 53 // both are meta. merge them. 54 out[k] = DeepMerge(outMetadataValue, maybe) 55 } 56 return out 57 } 58 59 // Loggable implements the Loggable interface 60 func (m Metadata) Loggable() map[string]interface{} { 61 // NB: method defined on value to avoid de-referencing nil Metadata 62 return m 63 } 64 65 func (m Metadata) JsonString() (string, error) { 66 // NB: method defined on value 67 b, err := json.Marshal(m) 68 return string(b), err 69 } 70 71 // Metadatify converts maps into Metadata 72 func Metadatify(i interface{}) (Metadata, error) { 73 value := reflect.ValueOf(i) 74 if value.Kind() == reflect.Map { 75 m := map[string]interface{}{} 76 for _, k := range value.MapKeys() { 77 m[k.String()] = value.MapIndex(k).Interface() 78 } 79 return Metadata(m), nil 80 } 81 return nil, errors.New("is not a map") 82 }