kubo/thirdparty/eventlog/metadata.go
2015-05-30 02:56:36 +02:00

83 lines
1.9 KiB
Go

package eventlog
import (
"encoding/json"
"errors"
"reflect"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/satori/go.uuid"
)
// Metadata is a convenience type for generic maps
type Metadata map[string]interface{}
// Uuid returns a Metadata with the string key and UUID value
func Uuid(key string) Metadata {
return Metadata{
key: uuid.NewV4().String(),
}
}
// DeepMerge merges the second Metadata parameter into the first.
// Nested Metadata are merged recursively. Primitives are over-written.
func DeepMerge(b, a Metadata) Metadata {
out := Metadata{}
for k, v := range b {
out[k] = v
}
for k, v := range a {
maybe, err := Metadatify(v)
if err != nil {
// if the new value is not meta. just overwrite the dest vaue
out[k] = v
continue
}
// it is meta. What about dest?
outv, exists := out[k]
if !exists {
// the new value is meta, but there's no dest value. just write it
out[k] = v
continue
}
outMetadataValue, err := Metadatify(outv)
if err != nil {
// the new value is meta and there's a dest value, but the dest
// value isn't meta. just overwrite
out[k] = v
continue
}
// both are meta. merge them.
out[k] = DeepMerge(outMetadataValue, maybe)
}
return out
}
// Loggable implements the Loggable interface
func (m Metadata) Loggable() map[string]interface{} {
// NB: method defined on value to avoid de-referencing nil Metadata
return m
}
func (m Metadata) JsonString() (string, error) {
// NB: method defined on value
b, err := json.Marshal(m)
return string(b), err
}
// Metadatify converts maps into Metadata
func Metadatify(i interface{}) (Metadata, error) {
value := reflect.ValueOf(i)
if value.Kind() == reflect.Map {
m := map[string]interface{}{}
for _, k := range value.MapKeys() {
m[k.String()] = value.MapIndex(k).Interface()
}
return Metadata(m), nil
}
return nil, errors.New("is not a map")
}