com.github.tonivade.purefun.Validator Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2021, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun;
import static com.github.tonivade.purefun.Function1.identity;
import static com.github.tonivade.purefun.Matcher1.isNotNull;
import static com.github.tonivade.purefun.Matcher1.not;
import static com.github.tonivade.purefun.Precondition.check;
import static com.github.tonivade.purefun.Precondition.checkNonNull;
import static com.github.tonivade.purefun.Precondition.checkPositive;
import static com.github.tonivade.purefun.type.Validation.mapN;
import java.util.regex.Pattern;
import com.github.tonivade.purefun.type.Validation;
import com.github.tonivade.purefun.type.Validation.Result;
@FunctionalInterface
public interface Validator {
Validation validate(T value);
default Validator mapError(Function1 super E, ? extends F> mapper) {
checkNonNull(mapper);
return value -> validate(value).mapError(mapper);
}
default Validator compose(Function1 super R, ? extends T> getter) {
checkNonNull(getter);
return value -> validate(getter.apply(value)).map(Function1.cons(value));
}
default Validator andThen(Validator then) {
checkNonNull(then);
return value -> validate(value).flatMap(then::validate);
}
default Validator, T> combine(Validator other) {
checkNonNull(other);
return combine(this, other);
}
static Validator from(Matcher1 super T> matcher, Producer extends E> error) {
checkNonNull(matcher);
checkNonNull(error);
return value -> matcher.match(value) ? Validation.valid(value) : Validation.invalid(error.get());
}
static Validator, Tuple2> product(Validator v1,
Validator v2) {
return product(v1, v2, identity());
}
static Validator> product(Validator v1,
Validator v2,
Function1, F> reduce) {
checkNonNull(v1);
checkNonNull(v2);
checkNonNull(reduce);
return value -> mapN(
v1.validate(value.get1()),
v2.validate(value.get2()),
Function2.cons(value))
.mapError(reduce);
}
static Validator, Tuple3> product(Validator v1,
Validator v2,
Validator v3) {
return product(v1, v2, v3, identity());
}
static Validator> product(Validator v1,
Validator v2,
Validator v3,
Function1, F> reduce) {
checkNonNull(v1);
checkNonNull(v2);
checkNonNull(v3);
checkNonNull(reduce);
return value -> mapN(
v1.validate(value.get1()),
v2.validate(value.get2()),
v3.validate(value.get3()),
Function3.cons(value))
.mapError(reduce);
}
static Validator, Tuple4> product(Validator v1,
Validator v2,
Validator v3,
Validator v4) {
return product(v1, v2, v3, v4, identity());
}
static Validator> product(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Function1, F> reduce) {
checkNonNull(v1);
checkNonNull(v2);
checkNonNull(v3);
checkNonNull(v4);
checkNonNull(reduce);
return value -> mapN(
v1.validate(value.get1()),
v2.validate(value.get2()),
v3.validate(value.get3()),
v4.validate(value.get4()),
Function4.cons(value))
.mapError(reduce);
}
static Validator, Tuple5> product(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Validator v5) {
return product(v1, v2, v3, v4, v5, identity());
}
static Validator> product(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Validator v5,
Function1, G> reduce) {
checkNonNull(v1);
checkNonNull(v2);
checkNonNull(v3);
checkNonNull(v4);
checkNonNull(v5);
checkNonNull(reduce);
return value -> mapN(
v1.validate(value.get1()),
v2.validate(value.get2()),
v3.validate(value.get3()),
v4.validate(value.get4()),
v5.validate(value.get5()),
Function5.cons(value))
.mapError(reduce);
}
static Validator, T> combine(Validator v1,
Validator v2) {
return combine(v1, v2, identity());
}
static Validator combine(Validator v1,
Validator v2,
Function1, F> reduce) {
checkNonNull(v1);
checkNonNull(v2);
checkNonNull(reduce);
return value -> mapN(
v1.validate(value),
v2.validate(value),
Function2.cons(value))
.mapError(reduce);
}
static Validator, T> combine(Validator v1,
Validator v2,
Validator v3) {
return combine(v1, v2, v3, identity());
}
static Validator combine(Validator v1,
Validator v2,
Validator v3,
Function1, F> reduce) {
return combine(combine(v1, v2), v3.mapError(Result::of), Result.flatten().andThen(reduce));
}
static Validator, T> combine(Validator v1,
Validator v2,
Validator v3,
Validator v4) {
return combine(v1, v2, v3, v4, identity());
}
static Validator combine(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Function1, F> reduce) {
return combine(combine(v1, v2, v3), v4.mapError(Result::of), Result.flatten().andThen(reduce));
}
static Validator, T> combine(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Validator v5) {
return combine(v1, v2, v3, v4, v5, identity());
}
static Validator combine(Validator v1,
Validator v2,
Validator v3,
Validator v4,
Validator v5,
Function1, F> reduce) {
return combine(combine(v1, v2, v3, v4), v5.mapError(Result::of), Result.flatten().andThen(reduce));
}
static Validator valid() {
return Validation::valid;
}
static Validator invalid(E error) {
return value -> Validation.invalid(error);
}
static Validator nonNull() {
return nonNull(() -> "require non null");
}
static Validator nonNull(Producer message) {
return Validator.from(isNotNull(), message);
}
static Validator nonNullAnd(Validator then) {
return nonNullAnd(() -> "require non null", then);
}
static Validator nonNullAnd(Producer message, Validator then) {
return Validator.nonNull(message).andThen(then);
}
static Validator equalsTo(T expected) {
return equalsTo(expected, () -> "require equals to " + expected);
}
static Validator equalsTo(T expected, Producer message) {
checkNonNull(expected, "expected should not be null");
return from(Matcher1.is(expected), message);
}
static Validator notEqualsTo(T expected) {
return notEqualsTo(expected, () -> "require not equals to " + expected);
}
static Validator notEqualsTo(T expected, Producer message) {
checkNonNull(expected, "expected should not be null");
return from(Matcher1.is(expected).negate(), message);
}
static Validator instanceOf(Class> clazz) {
return instanceOf(clazz, () -> "require instance of " + clazz);
}
static Validator instanceOf(Class> clazz, Producer message) {
checkNonNull(clazz, "expected should not be null");
return from(Matcher1.instanceOf(clazz), message);
}
static Validator nonEmpty() {
return nonEmpty(() -> "require non empty string");
}
static Validator nonEmpty(Producer message) {
return from(not(String::isEmpty), message);
}
static Validator upper() {
return upper(() -> "require uppercase string");
}
static Validator upper(Producer message) {
return from(value -> value.toUpperCase().equals(value), message);
}
static Validator lower() {
return lower(() -> "require lowercase string");
}
static Validator lower(Producer message) {
return from(value -> value.toLowerCase().equals(value), message);
}
static Validator startsWith(String prefix) {
return startsWith(prefix, () -> "require start with: " + prefix);
}
static Validator startsWith(String prefix, Producer message) {
checkNonNull(prefix, "prefix should not be null");
return from(value -> value.startsWith(prefix), message);
}
static Validator contains(String substring) {
return contains(substring, () -> "require contain string: " + substring);
}
static Validator contains(String substring, Producer message) {
checkNonNull(substring, "substring should not be null");
return from(value -> value.contains(substring), message);
}
static Validator endsWith(String suffix) {
return endsWith(suffix, () -> "require end with: " + suffix);
}
static Validator endsWith(String suffix, Producer message) {
checkNonNull(suffix, "suffix should not be null");
return from(value -> value.endsWith(suffix), message);
}
static Validator match(String regex) {
return match(regex, () -> "should match expresion: " + regex);
}
static Validator match(String regex, Producer message) {
checkNonNull(regex, "regex should not be null");
return from(value -> Pattern.matches(regex, value), message);
}
static Validator minLength(int length) {
return minLength(length, () -> "require min length: " + length);
}
static Validator minLength(int length, Producer message) {
checkPositive(length, "length should be a positive value");
return greaterThanOrEqual(length, message).compose(String::length);
}
static Validator maxLength(int length) {
return maxLength(length, () -> "require max length: " + length);
}
static Validator maxLength(int length, Producer message) {
checkPositive(length, "length should be a positive value");
return lowerThan(length, message).compose(String::length);
}
static Validator positive() {
return greaterThan(0);
}
static Validator positive(Producer message) {
return greaterThan(0, message);
}
static Validator negative() {
return lowerThan(0);
}
static Validator negative(Producer message) {
return lowerThan(0, message);
}
static > Validator greaterThan(T min) {
return greaterThan(min, () -> "require greater than: " + min);
}
static > Validator greaterThan(T min, Producer message) {
return from(value -> min.compareTo(value) < 0, message);
}
static > Validator greaterThanOrEqual(T min) {
return greaterThanOrEqual(min, () -> "require greater than or equal to: " + min);
}
static > Validator greaterThanOrEqual(T min, Producer message) {
return from(value -> min.compareTo(value) <= 0, message);
}
static > Validator lowerThan(T max) {
return lowerThan(max, () -> "require lower than: " + max);
}
static > Validator lowerThan(T max, Producer message) {
return from(value -> value.compareTo(max) < 0, message);
}
static > Validator lowerThanOrEqual(T max) {
return lowerThanOrEqual(max, () -> "require lower than: " + max);
}
static > Validator lowerThanOrEqual(T max, Producer message) {
return from(value -> value.compareTo(max) <= 0, message);
}
static Validator length(int min, int max) {
return length(min, max, Producer.cons(""));
}
static Validator length(int min, int max, Producer message) {
check(() -> min < max, min + " should not be greater than " + max);
return Validator.nonNull()
.andThen(combine(minLength(min), maxLength(max), join(message)));
}
static Validator range(int start, int end) {
return range(start, end, Producer.cons(""));
}
static Validator range(int start, int end, Producer message) {
check(() -> start < end, "start should not be greater than end");
return Validator.nonNull()
.andThen(combine(greaterThanOrEqual(start), lowerThan(end), join(message)));
}
static Function1, String> join() {
return result -> result.join(",");
}
static Function1, String> join(String separator) {
return result -> result.join(separator);
}
static Function1, String> join(Producer message) {
return result -> result.join(",", message);
}
static Function1, String> join(String separator, Producer message) {
return result -> result.join(separator, message);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy