Passed
Pull Request — main (#50)
by Igor
02:06
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
// Codes overrides default codes for produced violation.
104
func (c CountConstraint) Codes(minCode, maxCode, exactCode string) CountConstraint {
105 1
	c.minCode = minCode
106 1
	c.maxCode = maxCode
107 1
	c.exactCode = exactCode
108 1
	return c
109
}
110
111
// MinMessage sets the violation message that will be shown if the collection length is less than
112
// the minimum value. You can set custom template parameters for injecting its values
113
// into the final message. Also, you can use default parameters:
114
//
115
//	{{ count }} - the current collection size;
116
//	{{ limit }} - the lower limit.
117
func (c CountConstraint) MinMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
118 1
	c.minMessageTemplate = template
119 1
	c.minMessageParameters = parameters
120 1
	return c
121
}
122
123
// MaxMessage sets the violation message that will be shown if the collection length is greater than
124
// the maximum value. You can set custom template parameters for injecting its values
125
// into the final message. Also, you can use default parameters:
126
//
127
//	{{ count }} - the current collection size;
128
//	{{ limit }} - the upper limit.
129
func (c CountConstraint) MaxMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
130 1
	c.maxMessageTemplate = template
131 1
	c.maxMessageParameters = parameters
132 1
	return c
133
}
134
135
// ExactMessage sets the violation message that will be shown if minimum and maximum values are equal and
136
// the length of the collection is not exactly this value. You can set custom template parameters
137
// for injecting its values into the final message. Also, you can use default parameters:
138
//
139
//	{{ count }} - the current collection size;
140
//	{{ limit }} - the exact expected collection size.
141
func (c CountConstraint) ExactMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
142 1
	c.exactMessageTemplate = template
143 1
	c.exactMessageParameters = parameters
144 1
	return c
145
}
146
147
func (c CountConstraint) ValidateIterable(value generic.Iterable, scope validation.Scope) error {
148 1
	return c.ValidateCountable(value.Count(), scope)
149
}
150
151
func (c CountConstraint) ValidateCountable(count int, scope validation.Scope) error {
152 1
	if c.isIgnored {
153 1
		return nil
154
	}
155 1
	if c.checkMax && count > c.max {
156 1
		return c.newViolation(count, c.max, c.maxCode, c.maxMessageTemplate, c.maxMessageParameters, scope)
157
	}
158 1
	if c.checkMin && count < c.min {
159 1
		return c.newViolation(count, c.min, c.minCode, c.minMessageTemplate, c.minMessageParameters, scope)
160
	}
161
162 1
	return nil
163
}
164
165
func (c CountConstraint) newViolation(
166
	count, limit int,
167
	violationCode, template string,
168
	parameters validation.TemplateParameterList,
169
	scope validation.Scope,
170
) validation.Violation {
171 1
	if c.checkMin && c.checkMax && c.min == c.max {
172 1
		template = c.exactMessageTemplate
173 1
		parameters = c.exactMessageParameters
174 1
		violationCode = c.exactCode
175
	}
176
177 1
	return scope.BuildViolation(violationCode, template).
178
		SetPluralCount(limit).
179
		SetParameters(
180
			parameters.Prepend(
181
				validation.TemplateParameter{Key: "{{ count }}", Value: strconv.Itoa(count)},
182
				validation.TemplateParameter{Key: "{{ limit }}", Value: strconv.Itoa(limit)},
183
			)...,
184
		).
185
		CreateViolation()
186
}
187