Passed
Push — main ( 957b58...866640 )
by Igor
02:11 queued 24s
created

it.newCountConstraint   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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