OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package dskey |
| 6 |
| 7 import ( |
| 8 "encoding/json" |
| 9 |
| 10 ds "github.com/luci/gae/service/datastore" |
| 11 ) |
| 12 |
| 13 // Generic is an implementation of Key which doesn't rely on the |
| 14 // SDK's implementation. It differs slightly in that it's not recursive (and |
| 15 // thus cannot express some of the invalid Key's that the SDK implementation |
| 16 // can). In particular, it's not possible to have a Generic in a namespace |
| 17 // whose Parent() is in a different namespace. |
| 18 // |
| 19 // Generic also implements json.Marshaler and json.Unmarshaler so it's |
| 20 // suitable for use in structs which need to serialize both to json and to |
| 21 // datastore. |
| 22 type Generic struct { |
| 23 appID string |
| 24 namespace string |
| 25 toks []ds.KeyTok |
| 26 } |
| 27 |
| 28 var _ interface { |
| 29 ds.Key |
| 30 json.Marshaler |
| 31 json.Unmarshaler |
| 32 } = (*Generic)(nil) |
| 33 |
| 34 // NewToks creates a new Generic. It is the Key implementation |
| 35 // returned from the various PropertyMap serialization routines, as well as |
| 36 // the native key implementation for the in-memory implementation of gae. |
| 37 func NewToks(appID, ns string, toks []ds.KeyTok) *Generic { |
| 38 newToks := make([]ds.KeyTok, len(toks)) |
| 39 copy(newToks, toks) |
| 40 return &Generic{appID, ns, newToks} |
| 41 } |
| 42 |
| 43 // New is a wrapper around NewToks which has an interface similar |
| 44 // to NewKey in the SDK. |
| 45 func New(appID, ns, kind, stringID string, intID int64, parent ds.Key) *Generic
{ |
| 46 _, _, toks := Split(parent) |
| 47 newToks := make([]ds.KeyTok, len(toks)) |
| 48 copy(newToks, toks) |
| 49 newToks = append(newToks, ds.KeyTok{Kind: kind, StringID: stringID, IntI
D: intID}) |
| 50 return &Generic{appID, ns, newToks} |
| 51 } |
| 52 |
| 53 // NewFromEncoded decodes and returns a *Generic |
| 54 func NewFromEncoded(encoded string) (ret *Generic, err error) { |
| 55 ret = &Generic{} |
| 56 ret.appID, ret.namespace, ret.toks, err = ToksDecode(encoded) |
| 57 return |
| 58 } |
| 59 |
| 60 func (k *Generic) lastTok() ds.KeyTok { |
| 61 if len(k.toks) > 0 { |
| 62 return k.toks[len(k.toks)-1] |
| 63 } |
| 64 return ds.KeyTok{} |
| 65 } |
| 66 |
| 67 // AppID returns the application ID that this Key is for. |
| 68 func (k *Generic) AppID() string { return k.appID } |
| 69 |
| 70 // Namespace returns the namespace that this Key is for. |
| 71 func (k *Generic) Namespace() string { return k.namespace } |
| 72 |
| 73 // Kind returns the datastore kind of the entity. |
| 74 func (k *Generic) Kind() string { return k.lastTok().Kind } |
| 75 |
| 76 // StringID returns the string ID of the entity (if defined, otherwise ""). |
| 77 func (k *Generic) StringID() string { return k.lastTok().StringID } |
| 78 |
| 79 // IntID returns the int64 ID of the entity (if defined, otherwise 0). |
| 80 func (k *Generic) IntID() int64 { return k.lastTok().IntID } |
| 81 |
| 82 // String returns a human-readable version of this Key. |
| 83 func (k *Generic) String() string { return String(k) } |
| 84 |
| 85 // Incomplete returns true iff k doesn't have an id yet |
| 86 func (k *Generic) Incomplete() bool { return Incomplete(k) } |
| 87 |
| 88 // Valid returns true if this key is complete and suitable for use with the |
| 89 // datastore. See the package-level Valid function for more information. |
| 90 func (k *Generic) Valid(allowSpecial bool, aid, ns string) bool { |
| 91 return Valid(k, allowSpecial, aid, ns) |
| 92 } |
| 93 |
| 94 // PartialValid returns true if this key is suitable for use with a Put |
| 95 // operation. See the package-level PartialValid function for more information. |
| 96 func (k *Generic) PartialValid(aid, ns string) bool { |
| 97 return PartialValid(k, aid, ns) |
| 98 } |
| 99 |
| 100 // Parent returns the parent Key of this *Generic, or nil. The parent |
| 101 // will always have the concrete type of *Generic. |
| 102 func (k *Generic) Parent() ds.Key { |
| 103 if len(k.toks) <= 1 { |
| 104 return nil |
| 105 } |
| 106 return &Generic{k.appID, k.namespace, k.toks[:len(k.toks)-1]} |
| 107 } |
| 108 |
| 109 // MarshalJSON allows this key to be automatically marshaled by encoding/json. |
| 110 func (k *Generic) MarshalJSON() ([]byte, error) { |
| 111 return MarshalJSON(k) |
| 112 } |
| 113 |
| 114 // UnmarshalJSON allows this key to be automatically unmarshaled by encoding/jso
n. |
| 115 func (k *Generic) UnmarshalJSON(buf []byte) error { |
| 116 appID, namespace, toks, err := UnmarshalJSON(buf) |
| 117 if err != nil { |
| 118 return err |
| 119 } |
| 120 *k = *NewToks(appID, namespace, toks) |
| 121 return nil |
| 122 } |
OLD | NEW |