Index: service/datastore/properties.go |
diff --git a/service/datastore/properties.go b/service/datastore/properties.go |
index dfa91515cca6432f38b102d2a119ca230e3655b5..44466379baa6cd8f6f25ab351fe70072e003b018 100644 |
--- a/service/datastore/properties.go |
+++ b/service/datastore/properties.go |
@@ -314,22 +314,9 @@ func (p *Property) SetValue(value interface{}, is IndexSetting) (err error) { |
return |
} |
-// PropertyLoadSaver may be implemented by a user type, and Interface will |
-// use this interface to serialize the type instead of trying to automatically |
-// create a serialization codec for it with helper.GetPLS. |
-type PropertyLoadSaver interface { |
- // Load takes the values from the given map and attempts to save them into |
- // the underlying object (usually a struct or a PropertyMap). If a fatal |
- // error occurs, it's returned via error. If non-fatal conversion errors |
- // occur, error will be a MultiError containing one or more ErrFieldMismatch |
- // objects. |
- Load(PropertyMap) error |
- |
- // Save returns the current property as a PropertyMap. if withMeta is true, |
- // then the PropertyMap contains all the metadata (e.g. '$meta' fields) |
- // which was held by this PropertyLoadSaver. |
- Save(withMeta bool) (PropertyMap, error) |
- |
+// MetaGetter is a subinterface of PropertyLoadSaver, but is also used to |
+// abstract the meta argument for RawInterface.GetMulti. |
+type MetaGetter interface { |
// GetMeta will get information about the field which has the struct tag in |
// the form of `gae:"$<key>[,<default>]?"`. |
// |
@@ -362,6 +349,38 @@ type PropertyLoadSaver interface { |
// } |
GetMeta(key string) (interface{}, error) |
+ // GetMetaDefault is GetMeta, but with a default. |
+ // |
+ // If the metadata key is not available, or its type doesn't equal the |
+ // homogenized type of dflt, then dflt will be returned. |
+ // |
+ // Type homogenization: |
+ // signed integer types -> int64 |
+ // bool -> Toggle fields (bool) |
+ // |
+ // Example: |
+ // pls.GetMetaDefault("foo", 100).(int64) |
+ GetMetaDefault(key string, dflt interface{}) interface{} |
+} |
+ |
+// PropertyLoadSaver may be implemented by a user type, and Interface will |
+// use this interface to serialize the type instead of trying to automatically |
+// create a serialization codec for it with helper.GetPLS. |
+type PropertyLoadSaver interface { |
+ // Load takes the values from the given map and attempts to save them into |
+ // the underlying object (usually a struct or a PropertyMap). If a fatal |
+ // error occurs, it's returned via error. If non-fatal conversion errors |
+ // occur, error will be a MultiError containing one or more ErrFieldMismatch |
+ // objects. |
+ Load(PropertyMap) error |
+ |
+ // Save returns the current property as a PropertyMap. if withMeta is true, |
+ // then the PropertyMap contains all the metadata (e.g. '$meta' fields) |
+ // which was held by this PropertyLoadSaver. |
+ Save(withMeta bool) (PropertyMap, error) |
+ |
+ MetaGetter |
+ |
// SetMeta allows you to set the current value of the meta-keyed field. |
SetMeta(key string, val interface{}) error |
@@ -435,6 +454,10 @@ func (pm PropertyMap) GetMeta(key string) (interface{}, error) { |
return v[0].Value(), nil |
} |
+func (pm PropertyMap) GetMetaDefault(key string, dflt interface{}) interface{} { |
+ return GetMetaDefaultImpl(pm.GetMeta, key, dflt) |
+} |
+ |
// SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error |
// if `val` has an invalid type (e.g. not one supported by Property). |
func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
@@ -450,3 +473,19 @@ func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
func (pm PropertyMap) Problem() error { |
return nil |
} |
+ |
+// GetMetaDefaultImpl is the implementation of PropertyLoadSaver.GetMetaDefault. |
+// |
+// It takes the normal GetMeta function, the key and the default, and returns |
+// the value according to PropertyLoadSaver.GetMetaDefault. |
+func GetMetaDefaultImpl(gm func(string) (interface{}, error), key string, dflt interface{}) interface{} { |
+ cur, err := gm(key) |
+ if err != nil { |
+ return dflt |
+ } |
+ dflt, typ := UpconvertUnderlyingType(dflt, reflect.TypeOf(dflt)) |
+ if reflect.TypeOf(cur) != typ { |
+ return dflt |
+ } |
+ return cur |
+} |