OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "reflect" | 9 "reflect" |
10 | 10 |
11 "github.com/luci/luci-go/common/errors" | 11 "github.com/luci/luci-go/common/errors" |
12 ) | 12 ) |
13 | 13 |
14 type multiArgType struct { | 14 type multiArgType struct { |
15 valid bool | 15 valid bool |
16 | 16 |
17 » getKey func(nk newKeyFunc, slot reflect.Value) (Key, error) | 17 » getKey func(aid, ns string, slot reflect.Value) (*Key, error) |
18 getPM func(slot reflect.Value) (PropertyMap, error) | 18 getPM func(slot reflect.Value) (PropertyMap, error) |
19 setPM func(slot reflect.Value, pm PropertyMap) error | 19 setPM func(slot reflect.Value, pm PropertyMap) error |
20 » setKey func(slot reflect.Value, k Key) | 20 » setKey func(slot reflect.Value, k *Key) |
21 newElem func() reflect.Value | 21 newElem func() reflect.Value |
22 } | 22 } |
23 | 23 |
24 func (mat *multiArgType) GetKeysPMs(nk newKeyFunc, slice reflect.Value) ([]Key,
[]PropertyMap, error) { | 24 func (mat *multiArgType) GetKeysPMs(aid, ns string, slice reflect.Value) ([]*Key
, []PropertyMap, error) { |
25 » retKey := make([]Key, slice.Len()) | 25 » retKey := make([]*Key, slice.Len()) |
26 retPM := make([]PropertyMap, slice.Len()) | 26 retPM := make([]PropertyMap, slice.Len()) |
27 lme := errors.NewLazyMultiError(len(retKey)) | 27 lme := errors.NewLazyMultiError(len(retKey)) |
28 for i := range retKey { | 28 for i := range retKey { |
29 » » key, err := mat.getKey(nk, slice.Index(i)) | 29 » » key, err := mat.getKey(aid, ns, slice.Index(i)) |
30 if !lme.Assign(i, err) { | 30 if !lme.Assign(i, err) { |
31 retKey[i] = key | 31 retKey[i] = key |
32 pm, err := mat.getPM(slice.Index(i)) | 32 pm, err := mat.getPM(slice.Index(i)) |
33 if !lme.Assign(i, err) { | 33 if !lme.Assign(i, err) { |
34 retPM[i] = pm | 34 retPM[i] = pm |
35 } | 35 } |
36 } | 36 } |
37 } | 37 } |
38 return retKey, retPM, lme.Get() | 38 return retKey, retPM, lme.Get() |
39 } | 39 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 func multiArgTypeInvalid() multiArgType { | 77 func multiArgTypeInvalid() multiArgType { |
78 return multiArgType{} | 78 return multiArgType{} |
79 } | 79 } |
80 | 80 |
81 // multiArgTypePLS == []P | 81 // multiArgTypePLS == []P |
82 // *P implements PropertyLoadSaver | 82 // *P implements PropertyLoadSaver |
83 func multiArgTypePLS(et reflect.Type) multiArgType { | 83 func multiArgTypePLS(et reflect.Type) multiArgType { |
84 ret := multiArgType{ | 84 ret := multiArgType{ |
85 valid: true, | 85 valid: true, |
86 | 86 |
87 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 87 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
88 » » » return newKeyObjErr(nk, slot.Addr().Interface()) | 88 » » » return newKeyObjErr(aid, ns, slot.Addr().Interface()) |
89 }, | 89 }, |
90 getPM: func(slot reflect.Value) (PropertyMap, error) { | 90 getPM: func(slot reflect.Value) (PropertyMap, error) { |
91 return slot.Addr().Interface().(PropertyLoadSaver).Save(
true) | 91 return slot.Addr().Interface().(PropertyLoadSaver).Save(
true) |
92 }, | 92 }, |
93 setPM: func(slot reflect.Value, pm PropertyMap) error { | 93 setPM: func(slot reflect.Value, pm PropertyMap) error { |
94 return slot.Addr().Interface().(PropertyLoadSaver).Load(
pm) | 94 return slot.Addr().Interface().(PropertyLoadSaver).Load(
pm) |
95 }, | 95 }, |
96 » » setKey: func(slot reflect.Value, k Key) { | 96 » » setKey: func(slot reflect.Value, k *Key) { |
97 setKey(slot.Addr().Interface(), k) | 97 setKey(slot.Addr().Interface(), k) |
98 }, | 98 }, |
99 } | 99 } |
100 if et.Kind() == reflect.Map { | 100 if et.Kind() == reflect.Map { |
101 ret.newElem = func() reflect.Value { | 101 ret.newElem = func() reflect.Value { |
102 // Create a *map so that way slot.Addr() works above whe
n this is | 102 // Create a *map so that way slot.Addr() works above whe
n this is |
103 // called from Run(). Otherwise the map is 'unaddressabl
e' according | 103 // called from Run(). Otherwise the map is 'unaddressabl
e' according |
104 // to reflect. ¯\_(ツ)_/¯ | 104 // to reflect. ¯\_(ツ)_/¯ |
105 ptr := reflect.New(et) | 105 ptr := reflect.New(et) |
106 ptr.Elem().Set(reflect.MakeMap(et)) | 106 ptr.Elem().Set(reflect.MakeMap(et)) |
107 return ptr.Elem() | 107 return ptr.Elem() |
108 } | 108 } |
109 } else { | 109 } else { |
110 ret.newElem = func() reflect.Value { | 110 ret.newElem = func() reflect.Value { |
111 return reflect.New(et).Elem() | 111 return reflect.New(et).Elem() |
112 } | 112 } |
113 } | 113 } |
114 return ret | 114 return ret |
115 } | 115 } |
116 | 116 |
117 // multiArgTypePLSPtr == []*P | 117 // multiArgTypePLSPtr == []*P |
118 // *P implements PropertyLoadSaver | 118 // *P implements PropertyLoadSaver |
119 func multiArgTypePLSPtr(et reflect.Type) multiArgType { | 119 func multiArgTypePLSPtr(et reflect.Type) multiArgType { |
120 ret := multiArgType{ | 120 ret := multiArgType{ |
121 valid: true, | 121 valid: true, |
122 | 122 |
123 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 123 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
124 » » » return newKeyObjErr(nk, slot.Interface()) | 124 » » » return newKeyObjErr(aid, ns, slot.Interface()) |
125 }, | 125 }, |
126 getPM: func(slot reflect.Value) (PropertyMap, error) { | 126 getPM: func(slot reflect.Value) (PropertyMap, error) { |
127 return slot.Interface().(PropertyLoadSaver).Save(true) | 127 return slot.Interface().(PropertyLoadSaver).Save(true) |
128 }, | 128 }, |
129 setPM: func(slot reflect.Value, pm PropertyMap) error { | 129 setPM: func(slot reflect.Value, pm PropertyMap) error { |
130 return slot.Interface().(PropertyLoadSaver).Load(pm) | 130 return slot.Interface().(PropertyLoadSaver).Load(pm) |
131 }, | 131 }, |
132 » » setKey: func(slot reflect.Value, k Key) { | 132 » » setKey: func(slot reflect.Value, k *Key) { |
133 setKey(slot.Interface(), k) | 133 setKey(slot.Interface(), k) |
134 }, | 134 }, |
135 } | 135 } |
136 if et.Kind() == reflect.Map { | 136 if et.Kind() == reflect.Map { |
137 ret.newElem = func() reflect.Value { | 137 ret.newElem = func() reflect.Value { |
138 ptr := reflect.New(et) | 138 ptr := reflect.New(et) |
139 ptr.Elem().Set(reflect.MakeMap(et)) | 139 ptr.Elem().Set(reflect.MakeMap(et)) |
140 return ptr | 140 return ptr |
141 } | 141 } |
142 } else { | 142 } else { |
143 ret.newElem = func() reflect.Value { return reflect.New(et) } | 143 ret.newElem = func() reflect.Value { return reflect.New(et) } |
144 } | 144 } |
145 return ret | 145 return ret |
146 } | 146 } |
147 | 147 |
148 // multiArgTypeStruct == []S | 148 // multiArgTypeStruct == []S |
149 func multiArgTypeStruct(et reflect.Type) multiArgType { | 149 func multiArgTypeStruct(et reflect.Type) multiArgType { |
150 cdc := getCodec(et) | 150 cdc := getCodec(et) |
151 if cdc.problem != nil { | 151 if cdc.problem != nil { |
152 return multiArgTypeInvalid() | 152 return multiArgTypeInvalid() |
153 } | 153 } |
154 toPLS := func(slot reflect.Value) PropertyLoadSaver { | 154 toPLS := func(slot reflect.Value) PropertyLoadSaver { |
155 return &structPLS{slot, cdc} | 155 return &structPLS{slot, cdc} |
156 } | 156 } |
157 return multiArgType{ | 157 return multiArgType{ |
158 valid: true, | 158 valid: true, |
159 | 159 |
160 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 160 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
161 » » » return newKeyObjErr(nk, toPLS(slot)) | 161 » » » return newKeyObjErr(aid, ns, toPLS(slot)) |
162 }, | 162 }, |
163 getPM: func(slot reflect.Value) (PropertyMap, error) { | 163 getPM: func(slot reflect.Value) (PropertyMap, error) { |
164 return toPLS(slot).(PropertyLoadSaver).Save(true) | 164 return toPLS(slot).(PropertyLoadSaver).Save(true) |
165 }, | 165 }, |
166 setPM: func(slot reflect.Value, pm PropertyMap) error { | 166 setPM: func(slot reflect.Value, pm PropertyMap) error { |
167 return toPLS(slot).(PropertyLoadSaver).Load(pm) | 167 return toPLS(slot).(PropertyLoadSaver).Load(pm) |
168 }, | 168 }, |
169 » » setKey: func(slot reflect.Value, k Key) { | 169 » » setKey: func(slot reflect.Value, k *Key) { |
170 setKey(toPLS(slot), k) | 170 setKey(toPLS(slot), k) |
171 }, | 171 }, |
172 newElem: func() reflect.Value { | 172 newElem: func() reflect.Value { |
173 return reflect.New(et).Elem() | 173 return reflect.New(et).Elem() |
174 }, | 174 }, |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 // multiArgTypeStructPtr == []*S | 178 // multiArgTypeStructPtr == []*S |
179 func multiArgTypeStructPtr(et reflect.Type) multiArgType { | 179 func multiArgTypeStructPtr(et reflect.Type) multiArgType { |
180 cdc := getCodec(et) | 180 cdc := getCodec(et) |
181 if cdc.problem != nil { | 181 if cdc.problem != nil { |
182 return multiArgTypeInvalid() | 182 return multiArgTypeInvalid() |
183 } | 183 } |
184 toPLS := func(slot reflect.Value) PropertyLoadSaver { | 184 toPLS := func(slot reflect.Value) PropertyLoadSaver { |
185 return &structPLS{slot.Elem(), cdc} | 185 return &structPLS{slot.Elem(), cdc} |
186 } | 186 } |
187 return multiArgType{ | 187 return multiArgType{ |
188 valid: true, | 188 valid: true, |
189 | 189 |
190 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 190 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
191 » » » return newKeyObjErr(nk, toPLS(slot)) | 191 » » » return newKeyObjErr(aid, ns, toPLS(slot)) |
192 }, | 192 }, |
193 getPM: func(slot reflect.Value) (PropertyMap, error) { | 193 getPM: func(slot reflect.Value) (PropertyMap, error) { |
194 return toPLS(slot).(PropertyLoadSaver).Save(true) | 194 return toPLS(slot).(PropertyLoadSaver).Save(true) |
195 }, | 195 }, |
196 setPM: func(slot reflect.Value, pm PropertyMap) error { | 196 setPM: func(slot reflect.Value, pm PropertyMap) error { |
197 return toPLS(slot).(PropertyLoadSaver).Load(pm) | 197 return toPLS(slot).(PropertyLoadSaver).Load(pm) |
198 }, | 198 }, |
199 » » setKey: func(slot reflect.Value, k Key) { | 199 » » setKey: func(slot reflect.Value, k *Key) { |
200 setKey(toPLS(slot), k) | 200 setKey(toPLS(slot), k) |
201 }, | 201 }, |
202 newElem: func() reflect.Value { | 202 newElem: func() reflect.Value { |
203 return reflect.New(et) | 203 return reflect.New(et) |
204 }, | 204 }, |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 // multiArgTypeInterface == []I | 208 // multiArgTypeInterface == []I |
209 func multiArgTypeInterface() multiArgType { | 209 func multiArgTypeInterface() multiArgType { |
210 return multiArgType{ | 210 return multiArgType{ |
211 valid: true, | 211 valid: true, |
212 | 212 |
213 » » getKey: func(nk newKeyFunc, slot reflect.Value) (Key, error) { | 213 » » getKey: func(aid, ns string, slot reflect.Value) (*Key, error) { |
214 » » » return newKeyObjErr(nk, slot.Elem().Interface()) | 214 » » » return newKeyObjErr(aid, ns, slot.Elem().Interface()) |
215 }, | 215 }, |
216 getPM: func(slot reflect.Value) (PropertyMap, error) { | 216 getPM: func(slot reflect.Value) (PropertyMap, error) { |
217 pls := mkPLS(slot.Elem().Interface()) | 217 pls := mkPLS(slot.Elem().Interface()) |
218 return pls.Save(true) | 218 return pls.Save(true) |
219 }, | 219 }, |
220 setPM: func(slot reflect.Value, pm PropertyMap) error { | 220 setPM: func(slot reflect.Value, pm PropertyMap) error { |
221 pls := mkPLS(slot.Elem().Interface()) | 221 pls := mkPLS(slot.Elem().Interface()) |
222 return pls.Load(pm) | 222 return pls.Load(pm) |
223 }, | 223 }, |
224 » » setKey: func(slot reflect.Value, k Key) { | 224 » » setKey: func(slot reflect.Value, k *Key) { |
225 setKey(slot.Elem().Interface(), k) | 225 setKey(slot.Elem().Interface(), k) |
226 }, | 226 }, |
227 } | 227 } |
228 } | 228 } |
229 | 229 |
230 func newKeyObjErr(nk newKeyFunc, src interface{}) (Key, error) { | 230 func newKeyObjErr(aid, ns string, src interface{}) (*Key, error) { |
231 pls := mkPLS(src) | 231 pls := mkPLS(src) |
232 » if key, _ := pls.GetMetaDefault("key", nil).(Key); key != nil { | 232 » if key, _ := pls.GetMetaDefault("key", nil).(*Key); key != nil { |
233 return key, nil | 233 return key, nil |
234 } | 234 } |
235 | 235 |
236 // get kind | 236 // get kind |
237 kind := pls.GetMetaDefault("kind", "").(string) | 237 kind := pls.GetMetaDefault("kind", "").(string) |
238 if kind == "" { | 238 if kind == "" { |
239 return nil, fmt.Errorf("unable to extract $kind from %T", src) | 239 return nil, fmt.Errorf("unable to extract $kind from %T", src) |
240 } | 240 } |
241 | 241 |
242 // get id - allow both to be default for default keys | 242 // get id - allow both to be default for default keys |
243 sid := pls.GetMetaDefault("id", "").(string) | 243 sid := pls.GetMetaDefault("id", "").(string) |
244 iid := pls.GetMetaDefault("id", 0).(int64) | 244 iid := pls.GetMetaDefault("id", 0).(int64) |
245 | 245 |
246 // get parent | 246 // get parent |
247 » par, _ := pls.GetMetaDefault("parent", nil).(Key) | 247 » par, _ := pls.GetMetaDefault("parent", nil).(*Key) |
248 | 248 |
249 » return nk(kind, sid, iid, par), nil | 249 » return NewKey(aid, ns, kind, sid, iid, par), nil |
250 } | 250 } |
251 | 251 |
252 func setKey(src interface{}, key Key) { | 252 func setKey(src interface{}, key *Key) { |
253 pls := mkPLS(src) | 253 pls := mkPLS(src) |
254 if pls.SetMeta("key", key) == ErrMetaFieldUnset { | 254 if pls.SetMeta("key", key) == ErrMetaFieldUnset { |
255 » » if key.StringID() != "" { | 255 » » lst := key.Last() |
256 » » » pls.SetMeta("id", key.StringID()) | 256 » » if lst.StringID != "" { |
| 257 » » » _ = pls.SetMeta("id", lst.StringID) |
257 } else { | 258 } else { |
258 » » » pls.SetMeta("id", key.IntID()) | 259 » » » _ = pls.SetMeta("id", lst.IntID) |
259 } | 260 } |
260 » » pls.SetMeta("kind", key.Kind()) | 261 » » _ = pls.SetMeta("kind", lst.Kind) |
261 » » pls.SetMeta("parent", key.Parent()) | 262 » » _ = pls.SetMeta("parent", key.Parent()) |
262 } | 263 } |
263 } | 264 } |
264 | 265 |
265 func mkPLS(o interface{}) PropertyLoadSaver { | 266 func mkPLS(o interface{}) PropertyLoadSaver { |
266 if pls, ok := o.(PropertyLoadSaver); ok { | 267 if pls, ok := o.(PropertyLoadSaver); ok { |
267 return pls | 268 return pls |
268 } | 269 } |
269 return GetPLS(o) | 270 return GetPLS(o) |
270 } | 271 } |
OLD | NEW |