vavr Validation - więcej niż 8 metod walidujących

Odpowiedz Nowy wątek
2019-02-04 14:43

Rejestracja: 11 lat temu

Ostatnio: 7 godzin temu

0

Cześć,

czy ktoś może mi pomóc jak obejść limit 8 argumentów metody Validation.combine w vavrze?

Przykładowy kod:

public class Person {

    public final String name;
    public final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class PersonValidator {

    private static final String VALID_NAME_CHARS = "[a-zA-Z ]";
    private static final int MIN_AGE = 0;

    public Validation<Seq<String>, Person> validatePerson(String name, int age) {
        return Validation.combine(validateName(name), validateAge(age),
                validateAge2(age),validateAge3(age),
                validateAge4(age),validateAge5(age),
                validateAge6(age),validateAge7(age)
//                ,validateAge8(age),validateAge9(age)
                )
                .ap((s, integer, integer2, integer3, integer4, integer5, integer6, integer7) -> new Person(name, age));
    }

    private Validation<String, String> validateName(String name) {
        return CharSeq.of(name).replaceAll(VALID_NAME_CHARS, "").transform(seq -> seq.isEmpty()
                ? Validation.valid(name)
                : Validation.invalid("Name contains invalid characters: '"
                + seq.distinct().sorted() + "'"));
    }

    private Validation<String, Integer> validateAge(int age) {
        return age < 3
                ? Validation.invalid("embrion...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge2(int age) {
        return age < 6
                ? Validation.invalid("bobas...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge3(int age) {
        return age < 9
                ? Validation.invalid("berbec...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge4(int age) {
        return age < 15
                ? Validation.invalid("dziecko...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge5(int age) {
        return age < 18
                ? Validation.invalid("szczeniak...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge6(int age) {
        return age < 25
                ? Validation.invalid("szczyl...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge7(int age) {
        return age < 30
                ? Validation.invalid("dzban...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge8(int age) {
        return age < 50
                ? Validation.invalid("dziad...")
                : Validation.valid(age);
    }

    private Validation<String, Integer> validateAge9(int age) {
        return age < 70
                ? Validation.invalid("emeryt...")
                : Validation.valid(age);
    }

}

public class Tester {

    public static void main(String[] args) {
        PersonValidator personValidator = new PersonValidator();
        Person marian = new Person("Marian", 2);

        Validation<Seq<String>, Person> marianValidated = personValidator.validatePerson(marian.name, marian.age);

        System.out.println(marianValidated);
    }
}

Jak to rozbić, żeby uzyskać obiekt Validation<Seq<String>, Person> z listą więcej niż 8 komunikatów z błędną walidacją?


Pozostało 580 znaków

2019-02-05 14:27

Rejestracja: 11 lat temu

Ostatnio: 7 godzin temu

0

Generalnie w kolejnych wersjach vavra planowana jest zmiana w Validation z Function8 na List, aby uniknąć tego problemu z limitem.

Póki co wycombinowałem taki workaround:

public class ValidationUtils {

    public static <T> Validation<List<String>, T> chceckMultipleValidation(T object, Validation... validations) {
        List<String> invalidMessages = List.of(validations)
                .filter(validation -> validation.isInvalid())
                .map(invalid -> invalid.getError())
                .toStream()
                .flatMap(e -> ((e instanceof List) ? ((List<Object>) e).toStream() : Stream.of(e)))
                .collect(List.collector())
                .map(messages -> messages.toString());

        if (!invalidMessages.isEmpty())
            return Validation.invalid(invalidMessages);
        return Validation.valid(object);
    }
}

Teraz w naszych validatorach można dzielić walidację na mniejsze części i zwracać jedność tą metodą.

    public Validation<Seq<String>, Person> validatePerson(String name, int age) {

        Validation<String, String> nameValidated = validateName(name);
        Validation<Seq<String>, Integer> ageValidated = Validation.combine(validateAge(age),
                validateAge2(age), validateAge3(age),
                validateAge4(age), validateAge5(age),
                validateAge6(age), validateAge7(age))
                .ap((integer, integer2, integer3, integer4, integer5, integer6, integer7) -> age);
        Person person = new Person(name, age);
        Validation validation = ValidationUtils.chceckMultipleValidation(person, nameValidated, ageValidated);
        return validation;
    }

W wyniku dostaniemy odpowiedni obiekt Validation, tj. invalid z listą błędów lub valid z naszym obiektem.

    public static void main(String[] args) {
        PersonValidator personValidator = new PersonValidator();
        Person marian = new Person("Marian", 100);

        Validation<Seq<String>, Person> marianValidated = personValidator.validatePerson(marian.name, marian.age);

        if (marianValidated.isInvalid()) {
            System.out.println(marianValidated.getError());
        } else {
            Person person = marianValidated.get();
            System.out.println(person);
        }
    }

edytowany 1x, ostatnio: kkojot, 2019-02-05 14:29

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0