aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/pacien/lemonad/validation/Validation.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/pacien/lemonad/validation/Validation.java')
-rw-r--r--src/main/java/org/pacien/lemonad/validation/Validation.java129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/main/java/org/pacien/lemonad/validation/Validation.java b/src/main/java/org/pacien/lemonad/validation/Validation.java
new file mode 100644
index 0000000..04c1ed0
--- /dev/null
+++ b/src/main/java/org/pacien/lemonad/validation/Validation.java
@@ -0,0 +1,129 @@
1/*
2 * lemonad - Some functional sweetness for Java
3 * Copyright (C) 2019 Pacien TRAN-GIRARD
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19package org.pacien.lemonad.validation;
20
21import org.pacien.lemonad.attempt.Attempt;
22
23import java.util.Arrays;
24import java.util.List;
25import java.util.Objects;
26import java.util.function.BiConsumer;
27import java.util.function.Consumer;
28import java.util.function.Function;
29import java.util.stream.Stream;
30
31import lombok.NonNull;
32
33import static java.util.stream.Collectors.toUnmodifiableList;
34import static org.pacien.lemonad.attempt.Attempt.failure;
35import static org.pacien.lemonad.attempt.Attempt.success;
36
37/**
38 * Wraps the result of the validation of a subject.
39 *
40 * @param <S> the subject type,
41 * @param <E> the error type.
42 * @author pacien
43 */
44public interface Validation<S, E> {
45 /**
46 * @return whether no error have been reported during the validation.
47 */
48 boolean isValid();
49
50 /**
51 * @return whether some error have been reported during the validation.
52 */
53 boolean isInvalid();
54
55 /**
56 * @return the subject of the validation.
57 */
58 S getSubject();
59
60 /**
61 * @return the potentially empty list of reported validation errors.
62 */
63 List<E> getErrors();
64
65 /**
66 * @param consumer a subject consumer called if the validation is successful.
67 * @return the current object.
68 */
69 default Validation<S, E> ifValid(@NonNull Consumer<? super S> consumer) {
70 if (isValid()) consumer.accept(getSubject());
71 return this;
72 }
73
74 /**
75 * @param consumer the consumer called with the validation subject and reported errors if the validation is failed.
76 * @return the current object.
77 */
78 default Validation<S, E> ifInvalid(@NonNull BiConsumer<? super S, ? super List<? super E>> consumer) {
79 if (!isValid()) consumer.accept(getSubject(), getErrors());
80 return this;
81 }
82
83 /**
84 * @return an {@link Attempt} with a state corresponding to the one of the validation.
85 */
86 default Attempt<S, List<E>> toAttempt() {
87 return isValid() ? success(getSubject()) : failure(getErrors());
88 }
89
90 /**
91 * @param mapper a function transforming a {@link Validation}.
92 * @return the transformed {@link Validation}.
93 */
94 default <SS, EE> Validation<SS, EE> flatMap(@NonNull Function<? super Validation<? super S, ? super E>, ? extends Validation<? extends SS, ? extends EE>> mapper) {
95 //noinspection unchecked
96 return (Validation<SS, EE>) mapper.apply(this);
97 }
98
99 /**
100 * @param subject an overriding subject.
101 * @param validationResults a {@link Stream} of {@link Validation}s to merge.
102 * @return the merged {@link Validation} containing all errors from the supplied ones.
103 */
104 static <S, E> Validation<S, E> merge(S subject, @NonNull Stream<? extends Validation<?, ? extends E>> validationResults) {
105 return new ValidationContainer<>(
106 subject,
107 validationResults.flatMap(res -> res.getErrors().stream()).collect(toUnmodifiableList()));
108 }
109
110 /**
111 * @param subject the suject of the validation.
112 * @return a successful {@link Validation}.
113 */
114 static <S, E> Validation<S, E> valid(S subject) {
115 return new ValidationContainer<>(subject, List.of());
116 }
117
118 /**
119 * @param subject the suject of the validation.
120 * @param error a validation error.
121 * @param errors additional validation errors.
122 * @return a failed {@link Validation} for the supplied subject.
123 */
124 @SafeVarargs static <S, E> Validation<S, E> invalid(S subject, E error, E... errors) {
125 return new ValidationContainer<>(
126 subject,
127 Stream.concat(Stream.of(error), Arrays.stream(errors)).map(Objects::requireNonNull).collect(toUnmodifiableList()));
128 }
129}