forked from rs/rest-layer
/
dependency.go
63 lines (57 loc) · 1.55 KB
/
dependency.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package schema
import "fmt"
// PreQuery stores a query as string so it can be parsed/validated later
type PreQuery struct {
s string
q Query
}
// Q is like ParseQuery, but returns an intermediate object which can
// be stored before behing parsed.
func Q(q string) *PreQuery {
return &PreQuery{s: q}
}
func (q *PreQuery) compile(v Validator) error {
if q.q == nil {
var err error
q.q, err = ParseQuery(q.s, v)
if err != nil {
return err
}
}
return nil
}
// compileDependencies recusively compiles all field.Dependency against the validator
// and report any error
func compileDependencies(s Schema, v Validator) error {
for _, def := range s.Fields {
if def.Dependency != nil {
if err := def.Dependency.compile(v); err != nil {
return err
}
}
if def.Schema != nil {
if err := compileDependencies(*def.Schema, v); err != nil {
return err
}
}
}
return nil
}
func (s Schema) validateDependencies(changes map[string]interface{}, doc map[string]interface{}, prefix string) (errs map[string][]interface{}) {
errs = map[string][]interface{}{}
for name, value := range changes {
path := prefix + name
field := s.GetField(path)
if field != nil && field.Dependency != nil {
if !field.Dependency.q.Match(doc) {
addFieldError(errs, name, fmt.Sprintf("does not match dependency: %s", field.Dependency.s))
}
}
if subChanges, ok := value.(map[string]interface{}); ok {
if subErrs := s.validateDependencies(subChanges, doc, path+"."); len(subErrs) > 0 {
addFieldError(errs, name, subErrs)
}
}
}
return errs
}