1 package jsonschema
2
3 import (
4 jptr "github.com/qri-io/jsonpointer"
5 )
6
7
8
9
10
11 type ValidationState struct {
12 Local *Schema
13 Root *Schema
14 RecursiveAnchor *Schema
15 BaseURI string
16 InstanceLocation *jptr.Pointer
17 RelativeLocation *jptr.Pointer
18 BaseRelativeLocation *jptr.Pointer
19
20 LocalRegistry *SchemaRegistry
21
22 EvaluatedPropertyNames *map[string]bool
23 LocalEvaluatedPropertyNames *map[string]bool
24 LastEvaluatedIndex int
25 LocalLastEvaluatedIndex int
26 Misc map[string]interface{}
27
28 Errs *[]KeyError
29 }
30
31
32 func NewValidationState(s *Schema) *ValidationState {
33 tmpBRLprt := jptr.NewPointer()
34 tmpRLprt := jptr.NewPointer()
35 tmpILprt := jptr.NewPointer()
36 return &ValidationState{
37 Root: s,
38 BaseRelativeLocation: &tmpBRLprt,
39 RelativeLocation: &tmpRLprt,
40 InstanceLocation: &tmpILprt,
41 LocalRegistry: &SchemaRegistry{},
42 LastEvaluatedIndex: -1,
43 LocalLastEvaluatedIndex: -1,
44 EvaluatedPropertyNames: &map[string]bool{},
45 LocalEvaluatedPropertyNames: &map[string]bool{},
46 Misc: map[string]interface{}{},
47 Errs: &[]KeyError{},
48 }
49 }
50
51
52 func (vs *ValidationState) NewSubState() *ValidationState {
53 return &ValidationState{
54 Local: vs.Local,
55 Root: vs.Root,
56 RecursiveAnchor: vs.RecursiveAnchor,
57 LastEvaluatedIndex: vs.LastEvaluatedIndex,
58 LocalLastEvaluatedIndex: vs.LocalLastEvaluatedIndex,
59 BaseURI: vs.BaseURI,
60 InstanceLocation: vs.InstanceLocation,
61 RelativeLocation: vs.RelativeLocation,
62 BaseRelativeLocation: vs.RelativeLocation,
63 LocalRegistry: vs.LocalRegistry,
64 EvaluatedPropertyNames: vs.EvaluatedPropertyNames,
65 LocalEvaluatedPropertyNames: vs.LocalEvaluatedPropertyNames,
66 Misc: map[string]interface{}{},
67 Errs: vs.Errs,
68 }
69 }
70
71
72 func (vs *ValidationState) ClearState() {
73 vs.EvaluatedPropertyNames = &map[string]bool{}
74 vs.LocalEvaluatedPropertyNames = &map[string]bool{}
75 if len(vs.Misc) > 0 {
76 vs.Misc = map[string]interface{}{}
77 }
78 }
79
80
81 func (vs *ValidationState) SetEvaluatedKey(key string) {
82 (*vs.EvaluatedPropertyNames)[key] = true
83 (*vs.LocalEvaluatedPropertyNames)[key] = true
84 }
85
86
87 func (vs *ValidationState) IsEvaluatedKey(key string) bool {
88 _, ok := (*vs.EvaluatedPropertyNames)[key]
89 return ok
90 }
91
92
93 func (vs *ValidationState) IsLocallyEvaluatedKey(key string) bool {
94 _, ok := (*vs.LocalEvaluatedPropertyNames)[key]
95 return ok
96 }
97
98
99 func (vs *ValidationState) SetEvaluatedIndex(i int) {
100 vs.LastEvaluatedIndex = i
101 vs.LocalLastEvaluatedIndex = i
102 }
103
104
105
106 func (vs *ValidationState) UpdateEvaluatedPropsAndItems(subState *ValidationState) {
107 joinSets(vs.EvaluatedPropertyNames, *subState.EvaluatedPropertyNames)
108 joinSets(vs.LocalEvaluatedPropertyNames, *subState.LocalEvaluatedPropertyNames)
109 if subState.LastEvaluatedIndex > vs.LastEvaluatedIndex {
110 vs.LastEvaluatedIndex = subState.LastEvaluatedIndex
111 }
112 if subState.LocalLastEvaluatedIndex > vs.LastEvaluatedIndex {
113 vs.LastEvaluatedIndex = subState.LocalLastEvaluatedIndex
114 }
115 }
116
117 func copySet(input map[string]bool) map[string]bool {
118 copy := make(map[string]bool, len(input))
119 for k, v := range input {
120 copy[k] = v
121 }
122 return copy
123 }
124
125 func joinSets(consumer *map[string]bool, supplier map[string]bool) {
126 for k, v := range supplier {
127 (*consumer)[k] = v
128 }
129 }
130
131
132 func (vs *ValidationState) AddError(data interface{}, msg string) {
133 schemaDebug("[AddError] Error: %s", msg)
134 instancePath := vs.InstanceLocation.String()
135 if len(instancePath) == 0 {
136 instancePath = "/"
137 }
138 *vs.Errs = append(*vs.Errs, KeyError{
139 PropertyPath: instancePath,
140 InvalidValue: data,
141 Message: msg,
142 })
143 }
144
145
146 func (vs *ValidationState) AddSubErrors(errs ...KeyError) {
147 for _, err := range errs {
148 schemaDebug("[AddSubErrors] Error: %s", err.Message)
149 }
150 *vs.Errs = append(*vs.Errs, errs...)
151 }
152
153
154 func (vs *ValidationState) IsValid() bool {
155 if vs.Errs == nil {
156 return true
157 }
158 return len(*vs.Errs) == 0
159 }
160
161
162 func (vs *ValidationState) DescendBase(token ...string) {
163 vs.DescendBaseFromState(vs, token...)
164 }
165
166
167 func (vs *ValidationState) DescendBaseFromState(base *ValidationState, token ...string) {
168 if base.BaseRelativeLocation != nil {
169 newPtr := base.BaseRelativeLocation.RawDescendant(token...)
170 vs.BaseRelativeLocation = &newPtr
171 }
172 }
173
174
175 func (vs *ValidationState) DescendRelative(token ...string) {
176 vs.DescendRelativeFromState(vs, token...)
177 }
178
179
180 func (vs *ValidationState) DescendRelativeFromState(base *ValidationState, token ...string) {
181 newPtr := base.InstanceLocation.RawDescendant(token...)
182 vs.RelativeLocation = &newPtr
183 }
184
185
186 func (vs *ValidationState) DescendInstance(token ...string) {
187 vs.DescendInstanceFromState(vs, token...)
188 }
189
190
191 func (vs *ValidationState) DescendInstanceFromState(base *ValidationState, token ...string) {
192 newPtr := base.InstanceLocation.RawDescendant(token...)
193 vs.InstanceLocation = &newPtr
194 }
195
View as plain text