/** * Writes changes from the bound fields to the given bean if all validators * (binding and bean level) pass. * <p> * If any field binding validator fails, no values are written and a * {@code ValidationException} is thrown. * <p> * If all field level validators pass, the given bean is updated and bean * level validators are run on the updated bean. If any bean level validator * fails, the bean updates are reverted and a {@code ValidationException} is * thrown. * * @see #writeBeanIfValid(Object) * @see #readBean(Object) * @see #setBean(Object) * * @param bean * the object to which to write the field values, not * {@code null} * @throws ValidationException * if some of the bound field values fail to validate */ public void writeBean(BEAN bean) throws ValidationException { BinderValidationStatus<BEAN> status = doWriteIfValid(bean, new ArrayList<>(bindings)); if (status.hasErrors()) { throw new ValidationException(status.getFieldValidationErrors(), status.getBeanValidationErrors()); } }
/** * Runs all currently configured field level validators, as well as all bean * level validators if a bean is currently set with * {@link #setBean(Object)}, and returns whether any of the validators * failed. * <p> * <b>Note:</b> Calling this method will not trigger status change events, * unlike {@link #validate()} and will not modify the UI. To also update * error indicators on fields, use {@code validate().isOk()}. * <p> * <strong>Note:</strong> This method will attempt to temporarily apply all * current changes to the bean and run full bean validation for it. The * changes are reverted after bean validation. * * @see #validate() * * @return whether this binder is in a valid state * @throws IllegalStateException * if bean level validators have been configured and no bean is * currently set */ public boolean isValid() { return validate(false).isOk(); }
/** * Convenience method for creating a unresolved validation status for the * given binder. * <p> * In practice this status means that the values might not be valid, but * validation errors should be hidden. * * @param source * the source binder * @return a unresolved validation status * @param <BEAN> * the bean type of the binder */ public static <BEAN> BinderValidationStatus<BEAN> createUnresolvedStatus( Binder<BEAN> source) { return new BinderValidationStatus<>(source, source.getBindings().stream().map( b -> BindingValidationStatus.createUnresolvedStatus(b)) .collect(Collectors.toList()), Collections.emptyList()); }
/** * Gets both field and bean level validation errors. * * @return a list of all validation errors */ public List<ValidationResult> getValidationErrors() { List<ValidationResult> errors = getFieldValidationErrors().stream() .map(s -> s.getResult().get()).collect(Collectors.toList()); errors.addAll(getBeanValidationErrors()); return errors; }
/** * The default binder level status handler. * <p> * Passes all field related results to the Binding status handlers. All * other status changes are displayed in the status label, if one has been * set with {@link #setStatusLabel(Label)}. * * @param binderStatus * status of validation results from binding and/or bean level * validators */ protected void handleBinderValidationStatus( BinderValidationStatus<BEAN> binderStatus) { // let field events go to binding status handlers binderStatus.notifyBindingValidationStatusHandlers(); // show first possible error or OK status in the label if set if (getStatusLabel().isPresent()) { String statusMessage = binderStatus.getBeanValidationErrors() .stream().findFirst().map(ValidationResult::getErrorMessage) .orElse(""); getStatusLabel().get().setValue(statusMessage); } }
if (status.isOk()) { } else { StringBuilder errors = new StringBuilder(); status.getFieldValidationErrors() .stream() .map(m -> m.getMessage().orElse(""))
BinderValidationStatus<BEAN> status = new BinderValidationStatus<>(this, bindingResults, binderResults); getValidationStatusHandler().statusChange(status); fireStatusChangeEvent(!status.isOk()); return status;
if (validators.isEmpty() || bindingStatuses.stream() .anyMatch(BindingValidationStatus::isError)) { validationStatus = new BinderValidationStatus<>(this, bindingStatuses, Collections.emptyList()); } else { .forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding) .writeFieldValue(getBean())); validationStatus = new BinderValidationStatus<>(this, bindingStatuses, validateBean(getBean())); restoreBeanState(getBean(), beanState); fireStatusChangeEvent(validationStatus.hasErrors());
private void doRemoveBean(boolean fireStatusEvent) { changedBindings.clear(); if (bean != null) { bean = null; } getValidationStatusHandler().statusChange( BinderValidationStatus.createUnresolvedStatus(this)); if (fireStatusEvent) { fireStatusChangeEvent(false); } }
/** * Notifies all validation status handlers in bindings. * * @see #notifyBindingValidationStatusHandlers(SerializablePredicate) * * @since 8.2 */ public void notifyBindingValidationStatusHandlers() { notifyBindingValidationStatusHandlers(t -> true); }
/** * Gets whether validation for the binder passed or not. * * @return {@code true} if validation has passed, {@code false} if not */ public boolean isOk() { return !hasErrors(); }
private Button.ClickListener addEntryClickListener(Binder binder) { return event -> { if (binder.validate().isOk()) { if (binder.writeBeanIfValid(binder.getBean())) { GLEntry entry = (GLEntry) binder.getBean(); BindingValidationStatus<?> result = (BindingValidationStatus<?>) binder.validate().getFieldValidationErrors().get(0); app.displayNotification(result.getResult().get().getErrorMessage());
}); getValidationStatusHandler().statusChange( BinderValidationStatus.createUnresolvedStatus(this)); fireStatusChangeEvent(false);
/** * Writes changes from the bound fields to the given bean if all validators * (binding and bean level) pass. * <p> * If any field binding validator fails, no values are written and * <code>false</code> is returned. * <p> * If all field level validators pass, the given bean is updated and bean * level validators are run on the updated bean. If any bean level validator * fails, the bean updates are reverted and <code>false</code> is returned. * * @see #writeBean(Object) * @see #readBean(Object) * @see #setBean(Object) * * @param bean * the object to which to write the field values, not * {@code null} * @return {@code true} if there was no validation errors and the bean was * updated, {@code false} otherwise */ public boolean writeBeanIfValid(BEAN bean) { return doWriteIfValid(bean, new ArrayList<>(bindings)).isOk(); }
@Override public BindingValidationStatus<TARGET> validate(boolean fireEvent) { Objects.requireNonNull(binder, "This Binding is no longer attached to a Binder"); BindingValidationStatus<TARGET> status = doValidation(); if (fireEvent) { getBinder().getValidationStatusHandler() .statusChange(new BinderValidationStatus<>(getBinder(), Arrays.asList(status), Collections.emptyList())); getBinder().fireStatusChangeEvent(status.isError()); } return status; }
BinderValidationStatus.createUnresolvedStatus(this)); fireStatusChangeEvent(false);
@Override public BinderValidationStatus<T> validate() { // noop return new BinderValidationStatus<>(this, Collections.emptyList(), Collections.emptyList()); }