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-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