com.github.tonivade.purefun.Validator Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2020, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun;
import com.github.tonivade.purefun.type.Validation;
import com.github.tonivade.purefun.type.Validation.Result;
import java.util.regex.Pattern;
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.type.Validation.map2;
import static com.github.tonivade.purefun.type.Validation.map3;
import static com.github.tonivade.purefun.type.Validation.map4;
import static com.github.tonivade.purefun.type.Validation.map5;
import static java.util.Objects.isNull;
import static java.util.Objects.requireNonNull;
@FunctionalInterface
public interface Validator {
Validation validate(T value);
default Validator mapError(Function1 mapper) {
requireNonNull(mapper);
return value -> validate(value).mapError(mapper);
}
default Validator compose(Function1 getter) {
requireNonNull(getter);
return value -> validate(getter.apply(value)).map(Function1.cons(value));
}
default Validator andThen(Validator then) {
requireNonNull(then);
return value -> validate(value).flatMap(then::validate);
}
static Validator from(Matcher1 matcher, Producer error) {
requireNonNull(matcher);
requireNonNull(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) {
requireNonNull(v1);
requireNonNull(v2);
requireNonNull(reduce);
return value -> map2(
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) {
requireNonNull(v1);
requireNonNull(v2);
requireNonNull(v3);
requireNonNull(reduce);
return value -> map3(
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) {
requireNonNull(v1);
requireNonNull(v2);
requireNonNull(v3);
requireNonNull(v4);
requireNonNull(reduce);
return value -> map4(
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) {
requireNonNull(v1);
requireNonNull(v2);
requireNonNull(v3);
requireNonNull(v4);
requireNonNull(v5);
requireNonNull(reduce);
return value -> map5(
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) {
requireNonNull(v1);
requireNonNull(v2);
requireNonNull(reduce);
return value -> map2(
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 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) {
if (isNull(prefix)) {
throw new IllegalArgumentException("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) {
if (isNull(substring)) {
throw new IllegalArgumentException("string 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) {
if (isNull(suffix)) {
throw new IllegalArgumentException("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) {
if (isNull(regex)) {
throw new IllegalArgumentException("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) {
if (length < 0) {
throw new IllegalArgumentException("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) {
if (length < 0) {
throw new IllegalArgumentException("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(int min) {
return greaterThan(min, () -> "require greater than: " + min);
}
static Validator greaterThan(int min, Producer message) {
return from(value -> value > min, message);
}
static Validator greaterThanOrEqual(int min) {
return greaterThanOrEqual(min, () -> "require greater than or equal to: " + min);
}
static Validator greaterThanOrEqual(int min, Producer message) {
return from(value -> value >= min, message);
}
static Validator lowerThan(int max) {
return lowerThan(max, () -> "require lower than: " + max);
}
static Validator lowerThan(int max, Producer message) {
return from(value -> value < max, message);
}
static Validator lowerThanOrEqual(int max) {
return lowerThanOrEqual(max, () -> "require lower than: " + max);
}
static Validator lowerThanOrEqual(int max, Producer message) {
return from(value -> value <= max, message);
}
static Validator length(int min, int max) {
return length(min, max, Producer.cons(""));
}
static Validator length(int min, int max, Producer message) {
if (min >= max) {
throw new IllegalArgumentException(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) {
if (start >= end) {
throw new IllegalArgumentException("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