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

jaxx.runtime.validator.swing.SwingValidator Maven / Gradle / Ivy

There is a newer version: 3.0-alpha-6
Show newest version
/*
 * *##% 
 * 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 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 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 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 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 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 cons = uiClass.getConstructor(BeanValidatorField.class); AbstractBeanValidatorUI ui = cons.newInstance(field); ui.setEnabled(true); JXLayer jx = (JXLayer) container; addBeanValidatorListener(ui); jx.setUI(ui); } } } }