Passed
Push — main ( aa8c07...4607a7 )
by Igor
02:58 queued 01:09
created

it.CountConstraint.ExactCode   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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