OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // HEAVILY adapted from github.com/golang/appengine/datastore | 5 // HEAVILY adapted from github.com/golang/appengine/datastore |
6 | 6 |
7 package datastore | 7 package datastore |
8 | 8 |
9 import ( | 9 import ( |
10 "fmt" | 10 "fmt" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 useExtra := false | 62 useExtra := false |
63 extra := (*PropertyMap)(nil) | 63 extra := (*PropertyMap)(nil) |
64 if i, ok := p.c.bySpecial["extra"]; ok { | 64 if i, ok := p.c.bySpecial["extra"]; ok { |
65 useExtra = true | 65 useExtra = true |
66 f := p.c.byIndex[i] | 66 f := p.c.byIndex[i] |
67 if f.canSet { | 67 if f.canSet { |
68 extra = p.o.Field(i).Addr().Interface().(*PropertyMap) | 68 extra = p.o.Field(i).Addr().Interface().(*PropertyMap) |
69 } | 69 } |
70 } | 70 } |
71 t := reflect.Type(nil) | 71 t := reflect.Type(nil) |
72 » for name, props := range propMap { | 72 » for name, pdata := range propMap { |
73 » » multiple := len(props) > 1 | 73 » » var props PropertySlice |
| 74 » » switch prop := pdata.(type) { |
| 75 » » case Property: |
| 76 » » » props = []Property{prop} |
| 77 |
| 78 » » case PropertySlice: |
| 79 » » » props = prop |
| 80 |
| 81 » » default: |
| 82 » » » panic(fmt.Errorf("unknown PropertyData type %T", prop)) |
| 83 » » } |
| 84 |
| 85 » » requireSlice := len(props) > 1 |
74 for i, prop := range props { | 86 for i, prop := range props { |
75 » » » if reason := loadInner(p.c, p.o, i, name, prop, multiple
); reason != "" { | 87 » » » if reason := loadInner(p.c, p.o, i, name, prop, requireS
lice); reason != "" { |
76 if useExtra { | 88 if useExtra { |
77 if extra != nil { | 89 if extra != nil { |
78 if *extra == nil { | 90 if *extra == nil { |
79 *extra = make(PropertyMa
p, 1) | 91 *extra = make(PropertyMa
p, 1) |
80 } | 92 } |
81 (*extra)[name] = props | 93 (*extra)[name] = props |
82 } | 94 } |
83 break // go to the next property in prop
Map | 95 break // go to the next property in prop
Map |
84 } else { | 96 } else { |
85 if t == nil { | 97 if t == nil { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 ret := PropertyMap(nil) | 246 ret := PropertyMap(nil) |
235 if withMeta { | 247 if withMeta { |
236 if p.mgs != nil { | 248 if p.mgs != nil { |
237 ret = p.mgs.GetAllMeta() | 249 ret = p.mgs.GetAllMeta() |
238 } else { | 250 } else { |
239 ret = p.GetAllMeta() | 251 ret = p.GetAllMeta() |
240 } | 252 } |
241 } else { | 253 } else { |
242 ret = make(PropertyMap, len(p.c.byName)) | 254 ret = make(PropertyMap, len(p.c.byName)) |
243 } | 255 } |
244 » if _, err := p.save(ret, "", ShouldIndex); err != nil { | 256 » if _, err := p.save(ret, "", nil, ShouldIndex); err != nil { |
245 return nil, err | 257 return nil, err |
246 } | 258 } |
247 return ret, nil | 259 return ret, nil |
248 } | 260 } |
249 | 261 |
250 func (p *structPLS) getDefaultKind() string { | 262 func (p *structPLS) getDefaultKind() string { |
251 if !p.o.IsValid() { | 263 if !p.o.IsValid() { |
252 return "" | 264 return "" |
253 } | 265 } |
254 return p.o.Type().Name() | 266 return p.o.Type().Name() |
255 } | 267 } |
256 | 268 |
257 func (p *structPLS) save(propMap PropertyMap, prefix string, is IndexSetting) (i
dxCount int, err error) { | 269 func (p *structPLS) save(propMap PropertyMap, prefix string, parentST *structTag
, is IndexSetting) (idxCount int, err error) { |
258 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { | 270 saveProp := func(name string, si IndexSetting, v reflect.Value, st *stru
ctTag) (err error) { |
259 if st.substructCodec != nil { | 271 if st.substructCodec != nil { |
260 » » » count, err := (&structPLS{v, st.substructCodec, nil}).sa
ve(propMap, name, si) | 272 » » » count, err := (&structPLS{v, st.substructCodec, nil}).sa
ve(propMap, name, st, si) |
261 if err == nil { | 273 if err == nil { |
262 idxCount += count | 274 idxCount += count |
263 if idxCount > maxIndexedProperties { | 275 if idxCount > maxIndexedProperties { |
264 err = errors.New("gae: too many indexed
properties") | 276 err = errors.New("gae: too many indexed
properties") |
265 } | 277 } |
266 } | 278 } |
267 return err | 279 return err |
268 } | 280 } |
269 | 281 |
270 prop := Property{} | 282 prop := Property{} |
271 if st.convert { | 283 if st.convert { |
272 prop, err = v.Addr().Interface().(PropertyConverter).ToP
roperty() | 284 prop, err = v.Addr().Interface().(PropertyConverter).ToP
roperty() |
273 } else { | 285 } else { |
274 err = prop.SetValue(v.Interface(), si) | 286 err = prop.SetValue(v.Interface(), si) |
275 } | 287 } |
276 if err != nil { | 288 if err != nil { |
277 return err | 289 return err |
278 } | 290 } |
279 » » propMap[name] = append(propMap[name], prop) | 291 |
| 292 » » // If we're a slice, or we are members in a slice, then use a Pr
opertySlice. |
| 293 » » if st.isSlice || (parentST != nil && parentST.isSlice) { |
| 294 » » » var pslice PropertySlice |
| 295 » » » if pdata := propMap[name]; pdata != nil { |
| 296 » » » » pslice = pdata.(PropertySlice) |
| 297 » » » } |
| 298 » » » propMap[name] = append(pslice, prop) |
| 299 » » } else { |
| 300 » » » if _, ok := propMap[name]; ok { |
| 301 » » » » return errors.New("non-slice property adding mul
tiple PropertyMap entries") |
| 302 » » » } |
| 303 » » » propMap[name] = prop |
| 304 » » } |
| 305 |
280 if prop.IndexSetting() == ShouldIndex { | 306 if prop.IndexSetting() == ShouldIndex { |
281 idxCount++ | 307 idxCount++ |
282 if idxCount > maxIndexedProperties { | 308 if idxCount > maxIndexedProperties { |
283 return errors.New("gae: too many indexed propert
ies") | 309 return errors.New("gae: too many indexed propert
ies") |
284 } | 310 } |
285 } | 311 } |
286 return nil | 312 return nil |
287 } | 313 } |
288 | 314 |
289 for i, st := range p.c.byIndex { | 315 for i, st := range p.c.byIndex { |
290 if st.name == "-" || st.isExtra { | 316 if st.name == "-" || st.isExtra { |
291 continue | 317 continue |
292 } | 318 } |
293 name := st.name | 319 name := st.name |
294 if prefix != "" { | 320 if prefix != "" { |
295 name = prefix + name | 321 name = prefix + name |
296 } | 322 } |
297 v := p.o.Field(i) | 323 v := p.o.Field(i) |
298 is1 := is | 324 is1 := is |
299 if st.idxSetting == NoIndex { | 325 if st.idxSetting == NoIndex { |
300 is1 = NoIndex | 326 is1 = NoIndex |
301 } | 327 } |
302 if st.isSlice { | 328 if st.isSlice { |
303 for j := 0; j < v.Len(); j++ { | 329 for j := 0; j < v.Len(); j++ { |
304 if err = saveProp(name, is1, v.Index(j), &st); e
rr != nil { | 330 if err = saveProp(name, is1, v.Index(j), &st); e
rr != nil { |
| 331 err = fmt.Errorf("gae: failed to save sl
ice field %q: %v", name, err) |
305 return | 332 return |
306 } | 333 } |
307 } | 334 } |
308 } else { | 335 } else { |
309 if err = saveProp(name, is1, v, &st); err != nil { | 336 if err = saveProp(name, is1, v, &st); err != nil { |
| 337 err = fmt.Errorf("gae: failed to save single fie
ld %q: %v", name, err) |
310 return | 338 return |
311 } | 339 } |
312 } | 340 } |
313 } | 341 } |
314 | 342 |
315 if i, ok := p.c.bySpecial["extra"]; ok { | 343 if i, ok := p.c.bySpecial["extra"]; ok { |
316 if p.c.byIndex[i].name != "-" { | 344 if p.c.byIndex[i].name != "-" { |
317 for fullName, vals := range p.o.Field(i).Interface().(Pr
opertyMap) { | 345 for fullName, vals := range p.o.Field(i).Interface().(Pr
opertyMap) { |
318 if _, ok := propMap[fullName]; !ok { | 346 if _, ok := propMap[fullName]; !ok { |
319 propMap[fullName] = vals | 347 propMap[fullName] = vals |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 | 391 |
364 func (p *structPLS) GetAllMeta() PropertyMap { | 392 func (p *structPLS) GetAllMeta() PropertyMap { |
365 needKind := true | 393 needKind := true |
366 ret := make(PropertyMap, len(p.c.byMeta)+1) | 394 ret := make(PropertyMap, len(p.c.byMeta)+1) |
367 for k, idx := range p.c.byMeta { | 395 for k, idx := range p.c.byMeta { |
368 if val, ok := p.getMetaFor(idx); ok { | 396 if val, ok := p.getMetaFor(idx); ok { |
369 p := Property{} | 397 p := Property{} |
370 if err := p.SetValue(val, NoIndex); err != nil { | 398 if err := p.SetValue(val, NoIndex); err != nil { |
371 continue | 399 continue |
372 } | 400 } |
373 » » » ret["$"+k] = []Property{p} | 401 » » » ret["$"+k] = p |
374 } | 402 } |
375 } | 403 } |
376 if needKind { | 404 if needKind { |
377 if _, ok := p.c.byMeta["kind"]; !ok { | 405 if _, ok := p.c.byMeta["kind"]; !ok { |
378 » » » ret["$kind"] = []Property{MkPropertyNI(p.getDefaultKind(
))} | 406 » » » ret["$kind"] = MkPropertyNI(p.getDefaultKind()) |
379 } | 407 } |
380 } | 408 } |
381 return ret | 409 return ret |
382 } | 410 } |
383 | 411 |
384 func (p *structPLS) SetMeta(key string, val interface{}) bool { | 412 func (p *structPLS) SetMeta(key string, val interface{}) bool { |
385 idx, ok := p.c.byMeta[key] | 413 idx, ok := p.c.byMeta[key] |
386 if !ok { | 414 if !ok { |
387 return false | 415 return false |
388 } | 416 } |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 switch val { | 705 switch val { |
678 case "on", "On", "true": | 706 case "on", "On", "true": |
679 return true, nil | 707 return true, nil |
680 case "off", "Off", "false": | 708 case "off", "Off", "false": |
681 return false, nil | 709 return false, nil |
682 } | 710 } |
683 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) | 711 return nil, fmt.Errorf("Toggle field has bad/missing default, go
t %q", val) |
684 } | 712 } |
685 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) | 713 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t
, val) |
686 } | 714 } |
OLD | NEW |