Łańcuch walidacji, a pominięcie iteracji

0

elo, może ktoś mi coś fajnego podpowie.

Mam w kodzie batchowy update, leci forem po kolekcji, robi ciąg walidacji, jeśli nie zwaliduje, wrzuca wiadomość i pomija dalsze wykonywania kodu w iteracji:

for (Czesc entry : batch) {
            Set<String> duplicatedParts = findDuplicatedParts(entry);
            if (!duplicatedParts.isEmpty()) {
                updateResult.addMessage(messageCreator.createDuplicatedPartsMessage(String.join(", ", duplicatedParts)));
                continue;
            }
            final ObjectKey czescKey = lookupPart(entry.getCzescValue());
            if (czescKey == null) {
                updateResult.addMessage(messageCreator.createValueNotFoundMessage("Część", entry.getCzescValue()));
                continue;
            }
            final EditableReferableObject czescInstance = structuredEditingSession.checkoutReferableObject(czescKey);
            if (isPartNotCzesc(czescInstance)) {
                LOGGER.info("Part is not Czesc" + czescKey);
                updateResult.addNotUpdatedEntry(czescKey, messageCreator.createNotCzescMessage(czescKey));
                continue;
            }
            final ObjectKey eco = lookupEco(entry.getEco());
            if (eco == null) {
                LOGGER.info("Eco doesn't exist: " + entry.getEco());
                updateResult.addNotUpdatedEntry(czescKey, messageCreator.createValueNotFoundMessage("Eco", entry.getEco()));
                continue;
            }
            final boolean updated = updateCableHarness(czescInstance, entry, eco);
            // wrzuc do bazki cokolwiek

            }

Chętnie bym to wszystko wyekstraktował jakoś ładnie, ale jak skipnąć wtedy iteracje po pierwszy failu walidacji? Istnieje jakiś fajny wzorzec nazwany na to?
Do tego każde załadowanie dodatkowych (np. wywołanie lookupPart, checkoutReferableObject, lookupEco) powinno odbyć się później, po każdej kolejnej walidacji, bo jest dość kosztowne i nie chcemy ładować wszystkiego od razu.

3

Chyba chodzi tobie o coś takiego: https://sii.pl/blog/chain-of-responsibility-an-elegant-way-to-handle-complex-validation/

Z grubsza to powinno wyglądać tak:

interface Validator<T> {
    ValidationResult validate(final T element);
}

class ValidatorChain implements Validator<Czesc> {
    private final List<Validator<Czesc>> chain;

    ValidatorChain(final List<Validator<Czesc>> chain) {
        this.chain = chain;
    }

    @Override
    public ValidationResult validate(Czesc element) {
        ValidationResult result = ValidationResult.correct();
        for (Validator<Czesc> validator: chain) {
            result = validator.validate(element);
            if (!result.isCorrect()) {
                break;
            }
        }
        
        return result;
    }
}

class ValidationResult {
    private static final ValidationResult OK_INSTANCE = new ValidationResult(true, "Correct");
    
    private final boolean correct;
    private final String message;

    private ValidationResult(boolean correct, String message) {
        this.correct = correct;
        this.message = message;
    }

    boolean isCorrect() {
        return correct;    
    }
    
    String getMessage() {
        return message;
    }
    
    static ValidationResult correct() {
        return OK_INSTANCE;
    }
    
    static ValidationResult invalid(final String message) {
        return new ValidationResult(false, message); 
    }
}
0

A można by dodać @FunctionalInterface dla Validator<T> skoro 1 metoda, jakby ktoś chciał pomachać z lambdami

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