org.nuiton.jaxx.validator.JAXXValidator Maven / Gradle / Ivy
/*
* #%L
* JAXX :: Validator
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.validator;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.jaxx.validator.swing.SwingValidator;
import org.nuiton.jaxx.validator.swing.SwingValidatorMessageTableModel;
import org.nuiton.jaxx.validator.swing.ValidatorField;
import org.nuiton.jaxx.validator.swing.tab.TabInfoWithValidator;
import javax.swing.JComponent;
import javax.swing.event.TableModelListener;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* The contract of a validator-able object.
*
* @author Tony Chemit - [email protected]
*/
public interface JAXXValidator {
Logger log = LogManager.getLogger(JAXXValidator.class);
/**
* Obtain a validator from his id
*
* @param validatorId validator id
* @return the associated validator, or null
if not find
*/
SwingValidator> getValidator(String validatorId);
/**
* @return the list of ids of all registered validator
*/
List getValidatorIds();
ArrayListMultimap getValidatorEditors();
ArrayListMultimap createValidatorEditors();
/**
* Init the fields representation.
*
* This method is generated and should be called each time the context name
* of a validator has changed, since when using method
* {@link SwingValidator#setFieldRepresentation(String, JComponent)}
* is invoked at init, if a field is not watched for the selected context,
* then after when changing context name, the field will not be notified of any changed...
*
* @since 2.2.1
*/
default void registerValidatorFields() {
ArrayListMultimap validatorEditors = getValidatorEditors();
setFieldRepresentation(validatorEditors);
}
default Stream> validatorsStream(Predicate idPredicate) {
return getValidatorIds().stream().filter(idPredicate).map(this::getValidator);
}
default void listenValidatorContextNameAndRefreshFields(SwingValidator> validator) {
PropertyChangeListener listener = evt -> {
SwingValidator> validator1 = (SwingValidator>) evt.getSource();
log.info(String.format("Context name changed to [%s] for validator %s", evt.getNewValue(), validator1.getType()));
registerValidatorFields();
};
validator.addPropertyChangeListener(SwingValidator.CONTEXT_PROPERTY, listener);
}
/**
* Each field found will be registered to his corresponding validator via
* the method {@link SwingValidator#setFieldRepresentation(String, JComponent)}.
*
* By default, this method is invoked in the generated method
* {@link JAXXValidator#registerValidatorFields()} by a generated jaxx-validator file.
*
* @param editors mapping to register
*/
default void setFieldRepresentation(Multimap editors) {
for (String validatorId : getValidatorIds()) {
SwingValidator> validator = getValidator(validatorId);
for (Map.Entry entry : editors.entries()) {
ValidatorField fieldAnnotation = entry.getValue();
JComponent editor = entry.getKey();
if (!validatorId.equals(fieldAnnotation.validatorId())) {
// not good validator, skip this field
continue;
}
String[] propertyNames = fieldAnnotation.propertyName();
for (String propertyName : propertyNames) {
log.info(String.format("Detects for validator [%s] property %s for editor %s", validatorId, propertyName, fieldAnnotation.editorName()));
validator.setFieldRepresentation(propertyName, editor);
}
}
}
}
/**
* To install all the stuff for validation on a {@link JAXXValidator} ui.
*
* It will first find and register all validator field via the method
* {@link JAXXValidator#registerValidatorFields()}, then for each
* validators it will install ui for it (says connect validator to ui via layers)
* and will reload attached bean to make visible bean validation state on ui.
*
* This method is always invoked by a generated jaxx-validator file at the
* end of the {@code $initialize_05_setProperties} method.
*/
default void installValidationUI() {
// first install fields with validation
registerValidatorFields();
// for each validator install uis + reload bean
validatorsStream(id -> true).filter(Objects::nonNull).forEach(validator -> {
// install uis
validator.installUIs();
// reload attached bean (to see validation on uis)
validator.reloadBean();
});
}
/**
* method to attach a bean to all validators of an JAXXObject.
*
* It is possible to exclude some validator to be treated.
*
* @param bean the bean to attach in validators (can be null)
* @param excludeIds the list of validator id to exclude
*/
@SuppressWarnings({"unchecked", "rawtypes"})
default void setValidatorBean(Object bean, String... excludeIds) {
List validatorIds = getValidatorIds();
if (excludeIds.length > 0) {
validatorIds = new ArrayList<>(validatorIds);
for (String excludeId : excludeIds) {
validatorIds.remove(excludeId);
}
}
// touch validator, only if fits the bean type (or bean is null)
validatorsStream(validatorIds::contains).filter(v -> bean == null || v.getType().isAssignableFrom(
bean.getClass())).forEach(validator -> ((SwingValidator) validator).setBean(bean));
}
/**
* method to set the changed property to all validators of an JAXXObject.
*
* It is possible to exclude some validator to be treated.
*
* @param newValue the new value to set in changed validator property
* @param excludeIds the list of validator id to exclude
*/
default void setValidatorChanged(boolean newValue, String... excludeIds) {
List validatorIds = new ArrayList<>(getValidatorIds());
if (excludeIds.length > 0) {
for (String excludeId : excludeIds) {
validatorIds.remove(excludeId);
}
}
validatorsStream(validatorIds::contains).forEach(validator -> validator.setChanged(newValue));
}
default void installTabUI(TabInfoWithValidator tab) {
TabInfoWithValidator.TabTableModelListener listener = new TabInfoWithValidator.TabTableModelListener(tab);
tab.getValidator().getErrorTableModel().addTableModelListener(listener);
}
default void uninstallTabUI(Collection tabEditors, SwingValidatorMessageTableModel errorTableModel) {
for (TableModelListener tableModelListener : errorTableModel.getTableModelListeners()) {
if (tableModelListener instanceof TabInfoWithValidator.TabTableModelListener) {
TabInfoWithValidator.TabTableModelListener tabTableModelListener = (TabInfoWithValidator.TabTableModelListener) tableModelListener;
if (tabEditors.contains(tabTableModelListener.getComponent())) {
errorTableModel.removeTableModelListener(tableModelListener);
}
}
}
}
}