-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConstraint.java
More file actions
143 lines (124 loc) · 4.73 KB
/
Constraint.java
File metadata and controls
143 lines (124 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package pl.ais.commons.bean.validation;
import pl.ais.commons.bean.validation.constrainable.Constrainable;
import pl.ais.commons.bean.validation.event.ConstraintViolated;
import pl.ais.commons.bean.validation.event.ValidationListener;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.function.BiFunction;
/**
* Defines the API contract for the Constraint.
*
* @param <T> the type of values supported by the constraint
* @author Warlock, AIS.PL
* @since 1.2.1
*/
public interface Constraint<T> extends BiFunction<Constrainable<? extends T>, ValidationListener, Boolean> {
/**
* Creates and returns composite constraint being conjunction of this and provided constraint.
*
* @param other constraint to be used for building conjunction with this one
* @return constraint being conjunction of this and provided constraint
*/
Constraint<T> and(@Nonnull final Constraint<T> other);
/**
* Verifies if given constrainable matches the constraint and reports violation if needed.
*
* @param constrainable the constrainable to be checked
* @param listener the validation listener observing constraint violations
* @return {@code true} if given constrainable matches the constraint, {@code false} otherwise
*/
@Override
@Nonnull
default Boolean apply(final Constrainable<? extends T> constrainable, final ValidationListener listener) {
final boolean matched = constrainable.apply(this);
if (!matched) {
listener.constraintViolated(new ConstraintViolated(this, constrainable));
}
return matched;
}
/**
* @return the message which should be used to describe this constraint
*/
String getMessage();
/**
* @return the message parameters
*/
Object[] getMessageParameters();
/**
* @return name of this constraint
*/
String getName();
/**
* Negates the name of the constraint by adding/removing 'not' at the beginning of the name.
*
* @return negated constraint name
*/
default String getNegatedName() {
char[] name = getName().toCharArray();
final StringBuilder builder = new StringBuilder();
// ... by cutting off / adding the 'not' prefix, ...
if ((name.length >= 3) && ('n' == name[0]) && ('o' == name[1]) && ('t' == name[2])) {
name = Arrays.copyOfRange(name, 3, name.length);
} else {
builder.append("not");
}
name[0] = Character.toUpperCase(name[0]);
builder.append(name);
return builder.toString();
}
/**
* Indicates if this constraint is active.
*
* @return {@code true} if this constraint is active, {@code false} otherwise
*/
boolean isActive();
/**
* Creates and returns constraint being negation of this one.
*
* @return constraint being negation of this one
*/
Constraint<T> negate();
/**
* Creates and returns composite constraint being disjunction of this one and provided constraint.
*
* @param other constraint to be used for building disjunction with this one
* @return constraint being disjunction of this one and provided constraint
*/
Constraint<T> or(@Nonnull final Constraint<T> other);
/**
* Evaluates this constraint on the given argument.
*
* <p><strong>Note:</strong> disabled constraints are matched by any candidates. Use {@link #isActive()} method to
* properly handle this situation.</p>
*
* @param candidate value to be matched against this constraint
* @return {@code true} if given argument matches this constraint, {@code false} otherwise
*/
boolean test(@Nullable T candidate);
/**
* Provides the constraint (de)activating method.
*
* @param active defines if this constraint is active
* @return constraint instance (for method invocation chaining)
*/
@Nonnull
Constraint<T> when(boolean active);
/**
* Provides the message (potentially parametrized) which should be used to describe the constraint.
*
* @param message the message (potentially parametrized)
* @param messageParameters the message parameters (if any)
* @return constraint instance (for method invocation chaining)
*/
@Nonnull
Constraint<T> withDescription(@Nonnull String message, Object... messageParameters);
/**
* Provides the message parameters which should be used to describe the constraint.
*
* @param messageParameters the message parameters (if any)
* @return constraint instance (for method invocation chaining)
*/
@Nonnull
Constraint<T> withMessageParameters(Object... messageParameters);
}