]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package schema |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ) | |
6 | ||
7 | // MultiLevelFieldReader reads from other field readers, | |
8 | // merging their results along the way in a specific order. You can specify | |
9 | // "levels" and name them in order to read only an exact level or up to | |
10 | // a specific level. | |
11 | // | |
12 | // This is useful for saying things such as "read the field from the state | |
13 | // and config and merge them" or "read the latest value of the field". | |
14 | type MultiLevelFieldReader struct { | |
15 | Readers map[string]FieldReader | |
16 | Levels []string | |
17 | } | |
18 | ||
19 | func (r *MultiLevelFieldReader) ReadField(address []string) (FieldReadResult, error) { | |
20 | return r.ReadFieldMerge(address, r.Levels[len(r.Levels)-1]) | |
21 | } | |
22 | ||
23 | func (r *MultiLevelFieldReader) ReadFieldExact( | |
24 | address []string, level string) (FieldReadResult, error) { | |
25 | reader, ok := r.Readers[level] | |
26 | if !ok { | |
27 | return FieldReadResult{}, fmt.Errorf( | |
28 | "Unknown reader level: %s", level) | |
29 | } | |
30 | ||
31 | result, err := reader.ReadField(address) | |
32 | if err != nil { | |
33 | return FieldReadResult{}, fmt.Errorf( | |
34 | "Error reading level %s: %s", level, err) | |
35 | } | |
36 | ||
37 | return result, nil | |
38 | } | |
39 | ||
40 | func (r *MultiLevelFieldReader) ReadFieldMerge( | |
41 | address []string, level string) (FieldReadResult, error) { | |
42 | var result FieldReadResult | |
43 | for _, l := range r.Levels { | |
44 | if r, ok := r.Readers[l]; ok { | |
45 | out, err := r.ReadField(address) | |
46 | if err != nil { | |
47 | return FieldReadResult{}, fmt.Errorf( | |
48 | "Error reading level %s: %s", l, err) | |
49 | } | |
50 | ||
51 | // TODO: computed | |
52 | if out.Exists { | |
53 | result = out | |
54 | } | |
55 | } | |
56 | ||
57 | if l == level { | |
58 | break | |
59 | } | |
60 | } | |
61 | ||
62 | return result, nil | |
63 | } |