Passed
Pull Request — main (#50)
by Igor
02:03
created

it.CountConstraint.MinMessage   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 2
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
package it
2
3
import (
4
	"strconv"
5
6
	"github.com/muonsoft/validation"
7
	"github.com/muonsoft/validation/code"
8
	"github.com/muonsoft/validation/generic"
9
	"github.com/muonsoft/validation/message"
10
)
11
12
// CountConstraint checks that a given collection's (array, slice or a map) length is between some minimum and
13
// maximum value.
14
type CountConstraint struct {
15
	isIgnored              bool
16
	checkMin               bool
17
	checkMax               bool
18
	min                    int
19
	max                    int
20
	minCode                string
21
	maxCode                string
22
	exactCode              string
23
	minMessageTemplate     string
24
	minMessageParameters   validation.TemplateParameterList
25
	maxMessageTemplate     string
26
	maxMessageParameters   validation.TemplateParameterList
27
	exactMessageTemplate   string
28
	exactMessageParameters validation.TemplateParameterList
29
}
30
31
func newCountConstraint(min int, max int, checkMin bool, checkMax bool) CountConstraint {
32 1
	return CountConstraint{
33
		min:                  min,
34
		max:                  max,
35
		checkMin:             checkMin,
36
		checkMax:             checkMax,
37
		minCode:              code.CountTooFew,
38
		maxCode:              code.CountTooMany,
39
		exactCode:            code.CountExact,
40
		minMessageTemplate:   message.CountTooFew,
41
		maxMessageTemplate:   message.CountTooMany,
42
		exactMessageTemplate: message.CountExact,
43
	}
44
}
45
46
// HasMinCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
47
// is greater than the minimum value.
48
//
49
// Example
50
//  v := []int{1, 2}
51
//  err := validator.ValidateIterable(v, it.HasMinCount(3))
52
func HasMinCount(min int) CountConstraint {
53 1
	return newCountConstraint(min, 0, true, false)
54
}
55
56
// HasMaxCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
57
// is less than the maximum value.
58
//
59
// Example
60
//  v := []int{1, 2}
61
//  err := validator.ValidateIterable(v, it.HasMaxCount(1))
62
func HasMaxCount(max int) CountConstraint {
63 1
	return newCountConstraint(0, max, false, true)
64
}
65
66
// HasCountBetween creates a CountConstraint that checks the length of the iterable (slice, array, or map)
67
// is between some minimum and maximum value.
68
//
69
// Example
70
//  v := []int{1, 2}
71
//  err := validator.ValidateIterable(v, it.HasCountBetween(3, 10))
72
func HasCountBetween(min int, max int) CountConstraint {
73 1
	return newCountConstraint(min, max, true, true)
74
}
75
76
// HasExactCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
77
// has exact value.
78
//
79
// Example
80
//  v := []int{1, 2}
81
//  err := validator.ValidateIterable(v, it.HasExactCount(3))
82
func HasExactCount(count int) CountConstraint {
83 1
	return newCountConstraint(count, count, true, true)
84
}
85
86
// Name is the constraint name.
87
func (c CountConstraint) Name() string {
88
	return "CountConstraint"
89
}
90
91
// SetUp always returns no error.
92
func (c CountConstraint) SetUp() error {
93 1
	return nil
94
}
95
96
// When enables conditional validation of this constraint. If the expression evaluates to false,
97
// then the constraint will be ignored.
98
func (c CountConstraint) When(condition bool) CountConstraint {
99 1
	c.isIgnored = !condition
100 1
	return c
101
}
102
103
// MinCode overrides default code for violation that will be shown if the
104
// collection length is less than the minimum value.
105
func (c CountConstraint) MinCode(code string) CountConstraint {
106 1
	c.minCode = code
107 1
	return c
108
}
109
110
// MaxCode overrides default code for violation that will be shown if the
111
// collection length is greater than the maximum value.
112
func (c CountConstraint) MaxCode(code string) CountConstraint {
113 1
	c.maxCode = code
114 1
	return c
115
}
116
117
// ExactCode overrides default code for violation that will be shown if minimum and
118
// maximum values are equal and the length of the collection is not exactly this value.
119
func (c CountConstraint) ExactCode(code string) CountConstraint {
120 1
	c.exactCode = code
121 1
	return c
122
}
123
124
// MinMessage sets the violation message that will be shown if the collection length is less than
125
// the minimum value. You can set custom template parameters for injecting its values
126
// into the final message. Also, you can use default parameters:
127
//
128
//	{{ count }} - the current collection size;
129
//	{{ limit }} - the lower limit.
130
func (c CountConstraint) MinMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
131 1
	c.minMessageTemplate = template
132 1
	c.minMessageParameters = parameters
133 1
	return c
134
}
135
136
// MaxMessage sets the violation message that will be shown if the collection length is greater than
137
// the maximum value. You can set custom template parameters for injecting its values
138
// into the final message. Also, you can use default parameters:
139
//
140
//	{{ count }} - the current collection size;
141
//	{{ limit }} - the upper limit.
142
func (c CountConstraint) MaxMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
143 1
	c.maxMessageTemplate = template
144 1
	c.maxMessageParameters = parameters
145 1
	return c
146
}
147
148
// ExactMessage sets the violation message that will be shown if minimum and maximum values are equal and
149
// the length of the collection is not exactly this value. You can set custom template parameters
150
// for injecting its values into the final message. Also, you can use default parameters:
151
//
152
//	{{ count }} - the current collection size;
153
//	{{ limit }} - the exact expected collection size.
154
func (c CountConstraint) ExactMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
155 1
	c.exactMessageTemplate = template
156 1
	c.exactMessageParameters = parameters
157 1
	return c
158
}
159
160
func (c CountConstraint) ValidateIterable(value generic.Iterable, scope validation.Scope) error {
161 1
	return c.ValidateCountable(value.Count(), scope)
162
}
163
164
func (c CountConstraint) ValidateCountable(count int, scope validation.Scope) error {
165 1
	if c.isIgnored {
166 1
		return nil
167
	}
168 1
	if c.checkMax && count > c.max {
169 1
		return c.newViolation(count, c.max, c.maxCode, c.maxMessageTemplate, c.maxMessageParameters, scope)
170
	}
171 1
	if c.checkMin && count < c.min {
172 1
		return c.newViolation(count, c.min, c.minCode, c.minMessageTemplate, c.minMessageParameters, scope)
173
	}
174
175 1
	return nil
176
}
177
178
func (c CountConstraint) newViolation(
179
	count, limit int,
180
	violationCode, template string,
181
	parameters validation.TemplateParameterList,
182
	scope validation.Scope,
183
) validation.Violation {
184 1
	if c.checkMin && c.checkMax && c.min == c.max {
185 1
		template = c.exactMessageTemplate
186 1
		parameters = c.exactMessageParameters
187 1
		violationCode = c.exactCode
188
	}
189
190 1
	return scope.BuildViolation(violationCode, template).
191
		SetPluralCount(limit).
192
		SetParameters(
193
			parameters.Prepend(
194
				validation.TemplateParameter{Key: "{{ count }}", Value: strconv.Itoa(count)},
195
				validation.TemplateParameter{Key: "{{ limit }}", Value: strconv.Itoa(limit)},
196
			)...,
197
		).
198
		CreateViolation()
199
}
200