jaxx.runtime.validator.swing.SwingValidator Maven / Gradle / Ivy
/*
* *##%
* JAXX Runtime
* Copyright (C) 2008 - 2009 CodeLutin
*
* 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
* .
* ##%*
*/
package jaxx.runtime.validator.swing;
import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI;
import jaxx.runtime.validator.swing.ui.IconValidationUI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdesktop.jxlayer.JXLayer;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import java.awt.Container;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import jaxx.runtime.validator.BeanValidator;
import jaxx.runtime.validator.BeanValidatorField;
/**
* La surcharge de {@link jaxx.runtime.validator.BeanValidator} pour les ui swing
*
* /**
*
* Permet d'ajouter facilement le support de la validation des champs d'un
* bean et de le relier a une interface graphique.
* Utilise xwork pour la validation et JXLayer pour la visualisation.
*
*
* Le mieux pour son integration dans Jaxx est de faire de la generation pour
* force la compilation du code suivant:
*
*
* myValidor.getBean().get();
*
*
* et ceci pour chaque field ajoute a la map fieldRepresentation. De cette
* facon meme si le champs field est en texte on a une verification de son
* existance a la compilation.
*
*
* La representation en tag pourrait etre
*
* <validator id="myValidator" beanClass="{Personne.class}" errorList="$list">
* <field name="name" component="$name"/>
* <field name="firstName" component="$firstName"/>
* <field name="birthDate" component="$birthDate"/>
* </validator>
* <validator beanClass="{Personne.class}" autoField="true" errorList="$list">
* <fieldRepresentation name="name" component="$lastName"/>
* </validator>
*
*
* dans le premier exemple on fait un mapping explicite des champs, mais on voit
* que le nom du composant graphique est le meme que celui du champs. Pour eviter
* de longue saisie, il est possible d'utiliser le flag autoField
* qui pour chaque champs du ayant une methode get du bean recherche un composant
* avec cet Id. Il est aussi possible de surcharge un champs explicitement
* comme ici name, dans le cas ou le composant qui porterait ce nom serait
* utilise pour autre chose.
*
*
* Il faut un handler particulier pour ce composant car les attributs
* beanClass et autoField ne sont present que dans le XML jaxx et
* servent a la generation. Il faut aussi prendre en compte les elements
* fieldRepresentation fils du tag validator.
*
*
* Voici ce que pourrait etre le code genere par jaxx
*
* // declaration du bean
* BeanValidator $myValidator;
* // init du bean
* protected void createMyValidator() {
* $myValidator = new BeanValidator();
* // genere seulement si autoField = true
* for (Method m : beanClass.getMethod()) {
* if (m.getName().startsWith("get")) {
* String fieldName = m.getName().substring(3).toLowerCase();
* $myValidator.setFieldRepresentation(fieldName, $objectMap.get(fieldName));
* }
* }
* // pour chaque tag fieldRepresentation
* myValidator.setFieldRepresentation("name", $lastName);
* // si beanClass est specifie et n'est pas Object, on force l'acces au champs
* // pour validation a la compilation
* $myValidator.getBean().getName();
* $objectMap.put("myValidator", $myValidator);
* }
*
*
* @param le type de bean a valider
* @author poussin
* @author chemit
* @version 1.0
*/
public class SwingValidator extends BeanValidator {
/** to use log facility, just put in your code: log.info(\"...\"); */
static private final Log log = LogFactory.getLog(SwingValidator.class);
static private final Class extends AbstractBeanValidatorUI> DEFAULT_UI_CLASS = IconValidationUI.class;
/** permet de faire le lien en un champs du bean et l'objet qui permet de l'editer */
protected Map fieldRepresentation;
/** Object servant a contenir la liste des erreurs */
protected SwingValidatorMessageListModel errorListModel;
/** Object servant a contenir la liste des erreurs */
protected SwingValidatorMessageTableModel errorTableModel;
/** ui renderer class */
protected Class extends AbstractBeanValidatorUI> uiClass;
public SwingValidator(Class beanClass, String contextName) {
super(beanClass, contextName);
fieldRepresentation = new HashMap();
}
/**
* To reload a bean in the validator.
*
* This method is used to reload ui, since some editors
* could not exist when validator is init, so some messages
* should not be attached to an editor.
*/
public void reloadBean() {
B b = getBean();
if (b != null) {
setBean(null);
setBean(b);
}
}
public JComponent getFieldRepresentation(String fieldname) {
return fieldRepresentation.get(fieldname);
}
public Class extends AbstractBeanValidatorUI> getUiClass() {
return uiClass;
}
public void setErrorListModel(SwingValidatorMessageListModel errorListModel) {
this.errorListModel = errorListModel;
if (errorListModel != null) {
// register the validator in the model list
errorListModel.registerValidator(this);
}
}
public void setErrorTableModel(SwingValidatorMessageTableModel errorTableModel) {
this.errorTableModel = errorTableModel;
if (errorTableModel != null) {
// register the validator in the model table
errorTableModel.registerValidator(this);
}
}
public void setUiClass(Class extends AbstractBeanValidatorUI> uiClass) {
this.uiClass = uiClass;
}
@Override
public void setContextName(String contextName) {
/*Map, List> oldListeners = new HashMap, List>();
for (ValidatorField field : fields) {
ValidatorErrorListener[] listeners = field.getValidatorErrorListeners();
List toReinject = new ArrayList();
for (ValidatorErrorListener listener : listeners) {
if (listener instanceof AbstractBeanValidatorUI) {
// this listener will be reinject via installUIs method
continue;
}
toReinject.add(listener);
}
oldListeners.put(field, toReinject);
}*/
super.setContextName(contextName);
// must reinstall ui
installUIs();
// reinject none ui listeners
/*for (Entry, List> entry : oldListeners.entrySet()) {
ValidatorField field = getField(entry.getKey().getName());
for (ValidatorErrorListener listener : entry.getValue()) {
field.addValidatorErrorListener(listener);
}
}
oldListeners.clear();*/
}
/**
* Permet d'indiquer le composant graphique responsable de l'affichage
* d'un attribut du bean
*
* @param fieldname the field name in the bean
* @param c the editor component for the field
*/
public void setFieldRepresentation(String fieldname, JComponent c) {
BeanValidatorField field = getField(fieldname);
if (field == null) {
// no field registred in the validator
log.warn("the field '" + fieldname + "' is not defined in validator (no rules on it)");
return;
}
fieldRepresentation.put(fieldname, c);
}
public void setFieldRepresentation(Map fieldRepresentation) {
for (Map.Entry e : fieldRepresentation.entrySet()) {
setFieldRepresentation(e.getKey(), e.getValue());
}
}
@Override
public SwingValidator> getParentValidator() {
return (SwingValidator>) super.getParentValidator();
}
public void setParentValidator(SwingValidator> parentValidator) {
super.setParentValidator(parentValidator);
}
/** install ui on required components */
public void installUIs() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (uiClass == null) {
// use the default one
uiClass = DEFAULT_UI_CLASS;
}
for (Entry entry : fieldRepresentation.entrySet()) {
try {
setMessageRepresentation(entry.getKey(), null, entry.getValue(), uiClass);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
});
}
protected void setMessageRepresentation(String fieldname, JComponent old, JComponent c, Class extends AbstractBeanValidatorUI> uiClass)
throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
if (old == c) {
// same component, nothing to do
return;
}
BeanValidatorField field = getField(fieldname);
if (field == null) {
// this case should not appear since fieldName has already been check in method addFieldRepresentation
return;
}
if (old != null) {
// suppression du jxlayer sous l'ancien composant
Container container = old.getParent();
if (container instanceof JXLayer>) {
JXLayer> jx = (JXLayer>) container;
Object ui = jx.getUI();
if (ui != null && ui instanceof AbstractBeanValidatorUI) {
removeBeanValidatorListener((AbstractBeanValidatorUI) ui);
}
jx.setUI(null);
}
}
if (c != null) {
// ajout du jxlayer sous ce composant
Container container = c.getParent();
if (container instanceof JXLayer>) {
Constructor extends AbstractBeanValidatorUI> cons = uiClass.getConstructor(BeanValidatorField.class);
AbstractBeanValidatorUI ui = cons.newInstance(field);
ui.setEnabled(true);
JXLayer jx = (JXLayer) container;
addBeanValidatorListener(ui);
jx.setUI(ui);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy