All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 mapper) {
    checkNonNull(mapper);
    return value -> validate(value).mapError(mapper);
  }

  default  Validator compose(Function1 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 matcher, Producer 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