// getTypeAndId will validate that the model is a pointer to a struct, and that it has a key.Key field name Id. func getTypeAndId(model interface{}) (typ reflect.Type, id key.Key, err error) { val := reflect.ValueOf(model) if val.Kind() != reflect.Ptr { err = errors.Errorf("%+v is not a pointer", model) return } if val.Elem().Kind() != reflect.Struct { err = errors.Errorf("%+v is not a pointer to a struct", model) return } typ = val.Elem().Type() idField, found := val.Elem().Type().FieldByName(idFieldName) if !found { err = errors.Errorf("%+v does not have a field named Id", model) return } if !idField.Type.AssignableTo(reflect.TypeOf(key.Key(""))) { err = errors.Errorf("%+v has an Id field of type %v, that isn't assignable to key.Key", model, idField.Type) return } if idField.Tag.Get("datastore") != "-" { err = errors.Errorf("%+v has an Id field stored in datastore, which will cause no end of trouble. Set the tag of the Id field to be `datastore:\"-\"`", model) return } id = val.Elem().FieldByName(idFieldName).Interface().(key.Key) if id.Kind() != typ.Name() && id.Kind() != typ.Name()+"Log" { err = errors.Errorf("You can only read and write types with keys with the type name, or type name + 'Log'. You tried to read or write a %v with key %v", typ, id) return } return }
func ToGAE(c appengine.Context, k key.Key) *datastore.Key { if len(k) < 1 { return nil } kind, stringID, intID, parent := k.Split() return datastore.NewKey(c, kind, stringID, intID, ToGAE(c, key.Key(parent))) }
func FromGAEWithoutValidate(k *datastore.Key) (result key.Key) { if k == nil { return key.Key("") } result = key.NewWithoutValidate(k.Kind(), k.StringID(), k.IntID(), FromGAEWithoutValidate(k.Parent())) return }
func FromGAE(k *datastore.Key) (result key.Key, err error) { if k == nil { return key.Key(""), nil } parent, err := FromGAE(k.Parent()) if err != nil { return } return key.New(k.Kind(), k.StringID(), k.IntID(), parent) }