1package spec
2
3// CommonValidations describe common JSON-schema validations
4type CommonValidations struct {
5	Maximum          *float64      `json:"maximum,omitempty"`
6	ExclusiveMaximum bool          `json:"exclusiveMaximum,omitempty"`
7	Minimum          *float64      `json:"minimum,omitempty"`
8	ExclusiveMinimum bool          `json:"exclusiveMinimum,omitempty"`
9	MaxLength        *int64        `json:"maxLength,omitempty"`
10	MinLength        *int64        `json:"minLength,omitempty"`
11	Pattern          string        `json:"pattern,omitempty"`
12	MaxItems         *int64        `json:"maxItems,omitempty"`
13	MinItems         *int64        `json:"minItems,omitempty"`
14	UniqueItems      bool          `json:"uniqueItems,omitempty"`
15	MultipleOf       *float64      `json:"multipleOf,omitempty"`
16	Enum             []interface{} `json:"enum,omitempty"`
17}
18
19// SetValidations defines all validations for a simple schema.
20//
21// NOTE: the input is the larger set of validations available for schemas.
22// For simple schemas, MinProperties and MaxProperties are ignored.
23func (v *CommonValidations) SetValidations(val SchemaValidations) {
24	v.Maximum = val.Maximum
25	v.ExclusiveMaximum = val.ExclusiveMaximum
26	v.Minimum = val.Minimum
27	v.ExclusiveMinimum = val.ExclusiveMinimum
28	v.MaxLength = val.MaxLength
29	v.MinLength = val.MinLength
30	v.Pattern = val.Pattern
31	v.MaxItems = val.MaxItems
32	v.MinItems = val.MinItems
33	v.UniqueItems = val.UniqueItems
34	v.MultipleOf = val.MultipleOf
35	v.Enum = val.Enum
36}
37
38type clearedValidation struct {
39	Validation string
40	Value      interface{}
41}
42
43type clearedValidations []clearedValidation
44
45func (c clearedValidations) apply(cbs []func(string, interface{})) {
46	for _, cb := range cbs {
47		for _, cleared := range c {
48			cb(cleared.Validation, cleared.Value)
49		}
50	}
51}
52
53// ClearNumberValidations clears all number validations.
54//
55// Some callbacks may be set by the caller to capture changed values.
56func (v *CommonValidations) ClearNumberValidations(cbs ...func(string, interface{})) {
57	done := make(clearedValidations, 0, 5)
58	defer func() {
59		done.apply(cbs)
60	}()
61
62	if v.Minimum != nil {
63		done = append(done, clearedValidation{Validation: "minimum", Value: v.Minimum})
64		v.Minimum = nil
65	}
66	if v.Maximum != nil {
67		done = append(done, clearedValidation{Validation: "maximum", Value: v.Maximum})
68		v.Maximum = nil
69	}
70	if v.ExclusiveMaximum {
71		done = append(done, clearedValidation{Validation: "exclusiveMaximum", Value: v.ExclusiveMaximum})
72		v.ExclusiveMaximum = false
73	}
74	if v.ExclusiveMinimum {
75		done = append(done, clearedValidation{Validation: "exclusiveMinimum", Value: v.ExclusiveMinimum})
76		v.ExclusiveMinimum = false
77	}
78	if v.MultipleOf != nil {
79		done = append(done, clearedValidation{Validation: "multipleOf", Value: v.MultipleOf})
80		v.MultipleOf = nil
81	}
82}
83
84// ClearStringValidations clears all string validations.
85//
86// Some callbacks may be set by the caller to capture changed values.
87func (v *CommonValidations) ClearStringValidations(cbs ...func(string, interface{})) {
88	done := make(clearedValidations, 0, 3)
89	defer func() {
90		done.apply(cbs)
91	}()
92
93	if v.Pattern != "" {
94		done = append(done, clearedValidation{Validation: "pattern", Value: v.Pattern})
95		v.Pattern = ""
96	}
97	if v.MinLength != nil {
98		done = append(done, clearedValidation{Validation: "minLength", Value: v.MinLength})
99		v.MinLength = nil
100	}
101	if v.MaxLength != nil {
102		done = append(done, clearedValidation{Validation: "maxLength", Value: v.MaxLength})
103		v.MaxLength = nil
104	}
105}
106
107// ClearArrayValidations clears all array validations.
108//
109// Some callbacks may be set by the caller to capture changed values.
110func (v *CommonValidations) ClearArrayValidations(cbs ...func(string, interface{})) {
111	done := make(clearedValidations, 0, 3)
112	defer func() {
113		done.apply(cbs)
114	}()
115
116	if v.MaxItems != nil {
117		done = append(done, clearedValidation{Validation: "maxItems", Value: v.MaxItems})
118		v.MaxItems = nil
119	}
120	if v.MinItems != nil {
121		done = append(done, clearedValidation{Validation: "minItems", Value: v.MinItems})
122		v.MinItems = nil
123	}
124	if v.UniqueItems {
125		done = append(done, clearedValidation{Validation: "uniqueItems", Value: v.UniqueItems})
126		v.UniqueItems = false
127	}
128}
129
130// Validations returns a clone of the validations for a simple schema.
131//
132// NOTE: in the context of simple schema objects, MinProperties, MaxProperties
133// and PatternProperties remain unset.
134func (v CommonValidations) Validations() SchemaValidations {
135	return SchemaValidations{
136		CommonValidations: v,
137	}
138}
139
140// HasNumberValidations indicates if the validations are for numbers or integers
141func (v CommonValidations) HasNumberValidations() bool {
142	return v.Maximum != nil || v.Minimum != nil || v.MultipleOf != nil
143}
144
145// HasStringValidations indicates if the validations are for strings
146func (v CommonValidations) HasStringValidations() bool {
147	return v.MaxLength != nil || v.MinLength != nil || v.Pattern != ""
148}
149
150// HasArrayValidations indicates if the validations are for arrays
151func (v CommonValidations) HasArrayValidations() bool {
152	return v.MaxItems != nil || v.MinItems != nil || v.UniqueItems
153}
154
155// HasEnum indicates if the validation includes some enum constraint
156func (v CommonValidations) HasEnum() bool {
157	return len(v.Enum) > 0
158}
159
160// SchemaValidations describes the validation properties of a schema
161//
162// NOTE: at this moment, this is not embedded in SchemaProps because this would induce a breaking change
163// in the exported members: all initializers using litterals would fail.
164type SchemaValidations struct {
165	CommonValidations
166
167	PatternProperties SchemaProperties `json:"patternProperties,omitempty"`
168	MaxProperties     *int64           `json:"maxProperties,omitempty"`
169	MinProperties     *int64           `json:"minProperties,omitempty"`
170}
171
172// HasObjectValidations indicates if the validations are for objects
173func (v SchemaValidations) HasObjectValidations() bool {
174	return v.MaxProperties != nil || v.MinProperties != nil || v.PatternProperties != nil
175}
176
177// SetValidations for schema validations
178func (v *SchemaValidations) SetValidations(val SchemaValidations) {
179	v.CommonValidations.SetValidations(val)
180	v.PatternProperties = val.PatternProperties
181	v.MaxProperties = val.MaxProperties
182	v.MinProperties = val.MinProperties
183}
184
185// Validations for a schema
186func (v SchemaValidations) Validations() SchemaValidations {
187	val := v.CommonValidations.Validations()
188	val.PatternProperties = v.PatternProperties
189	val.MinProperties = v.MinProperties
190	val.MaxProperties = v.MaxProperties
191	return val
192}
193
194// ClearObjectValidations returns a clone of the validations with all object validations cleared.
195//
196// Some callbacks may be set by the caller to capture changed values.
197func (v *SchemaValidations) ClearObjectValidations(cbs ...func(string, interface{})) {
198	done := make(clearedValidations, 0, 3)
199	defer func() {
200		done.apply(cbs)
201	}()
202
203	if v.MaxProperties != nil {
204		done = append(done, clearedValidation{Validation: "maxProperties", Value: v.MaxProperties})
205		v.MaxProperties = nil
206	}
207	if v.MinProperties != nil {
208		done = append(done, clearedValidation{Validation: "minProperties", Value: v.MinProperties})
209		v.MinProperties = nil
210	}
211	if v.PatternProperties != nil {
212		done = append(done, clearedValidation{Validation: "patternProperties", Value: v.PatternProperties})
213		v.PatternProperties = nil
214	}
215}
216