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

com.holonplatform.vaadin7.components.PropertyInputGroup Maven / Gradle / Ivy

/*
 * Copyright 2016-2017 Axioma srl.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.holonplatform.vaadin7.components;

import java.util.Optional;
import java.util.stream.Stream;

import com.holonplatform.core.Validator;
import com.holonplatform.core.Validator.ValidationException;
import com.holonplatform.core.i18n.Localizable;
import com.holonplatform.core.internal.utils.ObjectUtils;
import com.holonplatform.core.property.Property;
import com.holonplatform.core.property.PropertyBox;
import com.holonplatform.core.property.PropertyRenderer;
import com.holonplatform.core.property.PropertyRendererRegistry;
import com.holonplatform.vaadin7.components.Input.InputPropertyRenderer;
import com.holonplatform.vaadin7.components.PropertyBinding.PostProcessor;
import com.holonplatform.vaadin7.internal.components.DefaultPropertyInputGroup;
import com.holonplatform.vaadin7.internal.components.ValidationUtils;
import com.vaadin.ui.Label;

/**
 * A class to manage a group of {@link Input}s bound to a {@link Property} set, loading and obtaining property values in
 * and from {@link Input}s using the {@link PropertyBox} data container type.
 * 

* Supports overall {@link Validator}s registration to validate all the {@link Input} values, allowing cross input * validation, using a {@link PropertyBox} to represent the inputs value set. *

*

* By default, property {@link Input} components are obtained from the {@link PropertyRenderer}s registered in the * context {@link PropertyRendererRegistry}, if available. Custom {@link PropertyRenderer} registration is supported to * provide a custom behaviour for specific properties. *

*

* Default property values are supported using a {@link DefaultValueProvider}. The property default values are loaded * when {@link #clear()} or {@link #setValue(PropertyBox)} methods are invoked. *

*

* Convenience methods {@link #setEnabled(boolean)} and {@link #setReadOnly(boolean)} can be used to change the enabled * / read-only state for all the property bound {@link Input}s. *

* * @since 5.0.0 */ public interface PropertyInputGroup extends PropertySetBound, ValueHolder, Validatable { /** * Gets all the {@link Input}s that have been bound to a property. * @return An {@link Iterable} on all bound {@link Input}s */ Iterable> getInputs(); /** * Get the {@link Input} bound to given property, if any. * @param Property type * @param property Property for which to get the associated {@link Input} (not null) * @return Optional {@link Input} bound to given property */ Optional> getInput(Property property); /** * Return a {@link Stream} of the properties and their bound {@link Input}s of this input group. * @param Property type * @return Property-Input {@link PropertyBinding} stream */ Stream>> stream(); /** * Get the current property values collected into a {@link PropertyBox}, using the group configured properties as * property set. *

* For each property with a bound {@link Input} component, the property value is obtained from the {@link Input} * component through the {@link Input#getValue()} method. *

* @param validate true to check the validity of the property bound {@link Input}s and of this * {@link PropertyInputGroup} before returing the value, throwing a {@link ValidationException} if the * validation is not successful. * @return A {@link PropertyBox} containing the property values (never null) * @throws ValidationException If validate is true and an {@link Input} value is not valid * @throws OverallValidationException If the overall validation failed */ PropertyBox getValue(boolean validate); /** * Get the current property values collected into a {@link PropertyBox}, using the group configured properties as * property set. *

* For each property with a bound {@link Input} component, the property value is obtained from the {@link Input} * component through the {@link Input#getValue()} method. *

*

* The available {@link Input}s and the overall group validation is performed before returning the value, throwing a * {@link ValidationException} if the validation is not successful. *

* @return A {@link PropertyBox} containing the property values (never null) * @throws ValidationException If one or more input value is not valid, providing the validation error messages * @throws OverallValidationException If the overall validation failed * @see #getValue(boolean) * @see #getValueIfValid() */ @Override default PropertyBox getValue() { return getValue(true); } /** * Get the current property values collected into a {@link PropertyBox}, using the group configured properties as * property set, only if the property bound {@link Input}s and this {@link PropertyInputGroup} are valid *

* For each property with a bound {@link Input} component, the property value is obtained from the {@link Input} * component through the {@link Input#getValue()} method. *

* @return A {@link PropertyBox} containing the property values, or an empty Optional if validation failed */ Optional getValueIfValid(); /** * Set the current property values using a {@link PropertyBox}, loading the values to the available property bound * {@link Input}s through the {@link Input#setValue(Object)} method. *

* Only the properties which belong to the group's property set are taken into account. *

* @param propertyBox the {@link PropertyBox} which contains the property values to load. If null, all * the {@link Input} components are cleared. * @param validate true to check the validity of the property bound {@link Input}s and of this * {@link PropertyInputGroup}, throwing a {@link ValidationException} if the validation is not successful. * @throws ValidationException If validate is true and an {@link Input} value is not valid * @throws OverallValidationException If overall validation failed */ void setValue(PropertyBox propertyBox, boolean validate); /** * Set the current property values using a {@link PropertyBox}, loading the values to the available property bound * {@link Input}s through the {@link Input#setValue(Object)} method. *

* Only the properties which belong to the group's property set are taken into account. *

*

* By default, no value validation is performed using this method. *

* @param propertyBox the {@link PropertyBox} which contains the property values to load. If null, all * the {@link Input} components are cleared. * @see #setValue(PropertyBox, boolean) */ @Override default void setValue(PropertyBox propertyBox) { setValue(propertyBox, false); } /** * Set the read-only mode for all the group inputs. * @param readOnly true to set all inputs as read-only, false to unset */ void setReadOnly(boolean readOnly); /** * Updates the enabled state of all the group inputs. * @param enabled true to enable all group inputs, false to disable them */ void setEnabled(boolean enabled); /** * Get a {@link Builder} to create and setup a {@link PropertyInputGroup}. * @return {@link PropertyInputGroup} builder */ static PropertyInputGroupBuilder builder() { return new DefaultPropertyInputGroup.DefaultBuilder(); } // ------- /** * Interface to provide the default value for a {@link Property}. * @param Property type */ @FunctionalInterface public interface DefaultValueProvider { /** * Get the property default value * @param property Property (never null) * @return Default value */ T getDefaultValue(Property property); } // Builder /** * {@link PropertyInputGroup} builder. */ public interface PropertyInputGroupBuilder extends Builder { } /** * Base {@link PropertyInputGroup} builder. * @param Actual {@link PropertyInputGroup} type * @param Concrete builder type */ public interface Builder> { /** * Add given properties to the {@link PropertyInputGroup} property set. * @param

Property type * @param properties Properties to add * @return this */ @SuppressWarnings({ "rawtypes", "unchecked" })

B properties(P... properties); /** * Add given properties to the {@link PropertyInputGroup} property set. * @param

Property type * @param properties Properties to add (not null) * @return this */ @SuppressWarnings("rawtypes")

B properties(Iterable

properties); /** * Set the given property as read-only. If a property is read-only, the {@link Input} bound to the property will * be setted as read-only too, and its value will never be written to a {@link PropertyBox} nor validated. * @param Property type * @param property Property to set as read-only (not null) * @return this */ B readOnly(Property property); /** * Set the given property as required. If a property is required, the {@link Input} bound to the property will * be setted as required, and its validation will fail when empty. * @param Property type * @param property Property to set as required (not null) * @return this */ B required(Property property); /** * Set the given property as required, using given {@link Validator} to check the property value. If a property * is required, the {@link Input} bound to the property will be setted as required, and its validation will fail * when empty. * @param Property type * @param property Property to set as required (not null) * @param validator The {@link Validator} to use to check the required property value (not null) * @return this */ B required(Property property, Validator validator); /** * Set the given property as required. If a property is required, the {@link Input} bound to the property will * be setted as required, and its validation will fail when empty. * @param Property type * @param property Property to set as required (not null) * @param message The message to use to notify the required validation failure * @return this */ B required(Property property, Localizable message); /** * Set the given property as required. If a property is required, the {@link Input} bound to the property will * be setted as required, and its validation will fail when empty. * @param Property type * @param property Property to set as required (not null) * @param message The default message to use to notify the required validation failure * @param messageCode The message localization code * @param arguments Optional message translation arguments * @return this */ default B required(Property property, String message, String messageCode, Object... arguments) { return required(property, Localizable.builder().message(message).messageCode(messageCode) .messageArguments(arguments).build()); } /** * Set the given property as required. If a property is required, the {@link Input} bound to the property will * be setted as required, and its validation will fail when empty. * @param Property type * @param property Property to set as required (not null) * @param message The default message to use to notify the required validation failure * @return this */ default B required(Property property, String message) { return required(property, Localizable.builder().message(message).build()); } /** * Set the given property as hidden. If a property is hidden, the {@link Input} bound to the property will never * be generated, but its value will be written to a {@link PropertyBox} using * {@link PropertyInputGroup#getValue()}. * @param Property type * @param property Property to set as hidden (not null) * @return this */ B hidden(Property property); /** * Set the default value provider for given property. * @param Property type * @param property Property (not null) * @param defaultValueProvider DefaultValueProvider (not null) * @return this */ B defaultValue(Property property, DefaultValueProvider defaultValueProvider); /** * Adds a {@link Validator} to the {@link Input} bound to given property. * @param Property type * @param property Property (not null) * @param validator Validator to add (not null) * @return this */ B withValidator(Property property, Validator validator); /** * Adds a {@link com.vaadin.data.Validator} to the {@link Input} bound to given property. * @param Property type * @param property Property (not null) * @param validator Validator to add (not null) * @return this */ default B withValidator(Property property, com.vaadin.data.Validator validator) { return withValidator(property, ValidationUtils.asValidator(validator)); } /** * Adds a {@link Validator} to the {@link PropertyInputGroup}, using a {@link PropertyBox} to provide the * property values to validate. * @param validator Validator to add (not null) * @return this */ B withValidator(Validator validator); /** * Adds a {@link com.vaadin.data.Validator} to the {@link PropertyInputGroup}. * @param validator Validator to add (not null) * @return this */ default B withValidator(com.vaadin.data.Validator validator) { return withValidator(ValidationUtils.asValidator(validator)); } /** * Set the {@link ValidationStatusHandler} to use to track given property validation status * changes. * @param Property type * @param property Property for which to set the validation status handler * @param validationStatusHandler the {@link ValidationStatusHandler} to associate to given * property (not null) * @return this */ B validationStatusHandler(Property property, ValidationStatusHandler validationStatusHandler); /** * Set the {@link Label} to use to track given property validation status changes. * @param Property type * @param property Property for which to set the validation status label * @param statusLabel the status {@link Label} to use to track given property validation status * (not null) * @return this */ default B validationStatusHandler(Property property, Label statusLabel) { return validationStatusHandler(property, ValidationStatusHandler.label(statusLabel)); } /** * Set the {@link ValidationStatusHandler} to use to track all the properties validation status changes. *

* A specific {@link ValidationStatusHandler} for each property can be configured using * {@link #validationStatusHandler(Property, ValidationStatusHandler)}. *

* @param validationStatusHandler the {@link ValidationStatusHandler} to set * @return this */ B propertiesValidationStatusHandler(ValidationStatusHandler validationStatusHandler); /** * Set the {@link ValidationStatusHandler} to use to track overall validation status changes. * @param validationStatusHandler the {@link ValidationStatusHandler} to set (not null) * @return this */ B validationStatusHandler(ValidationStatusHandler validationStatusHandler); /** * Set the {@link Label} to use as status label to track overall validation status changes. * @param statusLabel the status {@link Label} to set (not null) * @return this */ default B validationStatusHandler(Label statusLabel) { return validationStatusHandler(ValidationStatusHandler.label(statusLabel)); } /** * Sets whether to validate the available {@link Input}s value every time the {@link Input} value changes. *

* Default is true. *

* @param validateOnValueChange true to perform value validation every time a {@link Input} value * changes, false if not * @return this */ B validateOnValueChange(boolean validateOnValueChange); /** * Set whether to stop validation at first validation failure. If true, only the first * {@link ValidationException} is thrown at validation, otherwise a {@link ValidationException} containing all * the occurred validation exception is thrown. * @param stopValidationAtFirstFailure true to stop validation at first validation failure * @return this */ B stopValidationAtFirstFailure(boolean stopValidationAtFirstFailure); /** * Set whether to stop overall validation at first validation failure. If true, only the first * {@link OverallValidationException} is thrown at validation, otherwise a {@link OverallValidationException} * containing all the occurred validation exception is thrown. *

* The overall validation is the one which is performed using validators added with * {@link #withValidator(Validator)} method. *

* @param stopOverallValidationAtFirstFailure true to stop overall validation at first validation * failure * @return this */ B stopOverallValidationAtFirstFailure(boolean stopOverallValidationAtFirstFailure); /** * Set to ignore any {@link Property} registered {@link Validator} when binding the property to an {@link Input} * component, i.e. to not inherit property {@link Validator}s when the property-input binding is performed. * @return this */ B ignorePropertyValidation(); /** * Set the specific {@link PropertyRenderer} to use to render the {@link Input} to bind to given * property. * @param Property type * @param property Property (not null) * @param renderer Property renderer (not null) * @return this */ B bind(Property property, PropertyRenderer, T> renderer); /** * Convenience method to set a specific {@link PropertyRenderer} to use to render the {@link Input} to bind to * given property using the {@link InputPropertyRenderer} functional interface. * @param Property type * @param property Property (not null) * @param renderer Property renderer (not null) * @return this */ default B bind(Property property, InputPropertyRenderer renderer) { ObjectUtils.argumentNotNull(property, "Property must be not null"); ObjectUtils.argumentNotNull(renderer, "Renderer must be not null"); return bind(property, (PropertyRenderer, T>) renderer); } /** * Bind the given property to given input instance. If the property was already bound * to a {@link Input}, the old input will be replaced by the new input. *

* This method also adds property validators to given {@link Input} when applicable. *

* @param Property type * @param property Property (not null) * @param input Input to bind (not null) * @return this */ default B bind(Property property, Input input) { ObjectUtils.argumentNotNull(property, "Property must be not null"); ObjectUtils.argumentNotNull(input, "Input must be not null"); return bind(property, p -> input); } /** * Set whether to ignore properties without a bound {@link Input}. Default is false, and an * exception is thrown if a property of the {@link PropertyInputGroup} cannot be bound to any input component. * @param ignoreMissingInputs Whether to ignore when the {@link Input} for a property is missing * @return this */ B ignoreMissingInputs(boolean ignoreMissingInputs); /** * Add a {@link PostProcessor} to allow further {@link Input} configuration before the input is actually bound * to a property. * @param postProcessor the {@link PostProcessor} to add (not null) * @return this */ B withPostProcessor(PostProcessor> postProcessor); /** * Build the {@link PropertyInputGroup}. * @return a new {@link PropertyInputGroup} instance */ G build(); } /** * {@link ValidationException} extension to discern inputs validation and overall container validation exceptions. */ @SuppressWarnings("serial") public class OverallValidationException extends ValidationException { /** * {@inheritDoc} */ public OverallValidationException(String message) { super(message); } /** * {@inheritDoc} */ public OverallValidationException(String message, String messageCode, Object... messageArguments) { super(message, messageCode, messageArguments); } /** * {@inheritDoc} */ public OverallValidationException(ValidationException... causes) { super(causes); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy