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

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

There is a newer version: 3.0-alpha-6
Show newest version
/*
 * #%L
 * JAXX :: Validator
 * 
 * $Id: SwingValidatorUtil.java 2741 2013-10-24 15:54:44Z tchemit $
 * $HeadURL: http://svn.nuiton.org/svn/jaxx/tags/jaxx-2.7/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java $
 * %%
 * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit
 * %%
 * 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 jaxx.runtime.validator.swing;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import jaxx.runtime.JAXXObject;
import jaxx.runtime.JAXXValidator;
import jaxx.runtime.SwingUtil;
import jaxx.runtime.validator.swing.meta.Validator;
import jaxx.runtime.validator.swing.meta.ValidatorField;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.nuiton.util.ReflectUtil;
import org.nuiton.validator.NuitonValidatorScope;
import org.nuiton.validator.bean.list.BeanListValidator;
import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage;
import org.nuiton.validator.bean.simple.SimpleBeanValidators;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import java.awt.Color;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import static org.nuiton.i18n.I18n.n_;

/**
 * The helper class for swing validation module.
 *
 * @author tchemit 
 */
public class SwingValidatorUtil extends SimpleBeanValidators {

    /** Logger */
    static private final Log log = LogFactory.getLog(SwingValidatorUtil.class);

    protected static EnumMap icons;

    protected static EnumMap colors;

    public static EnumMap getIcons() {
        if (icons == null) {
            icons = new EnumMap(NuitonValidatorScope.class);
            icons.put(NuitonValidatorScope.FATAL, SwingUtil.createImageIcon("fatal.png"));
            icons.put(NuitonValidatorScope.ERROR, SwingUtil.createImageIcon("error.png"));
            icons.put(NuitonValidatorScope.WARNING, SwingUtil.createImageIcon("warning.png"));
            icons.put(NuitonValidatorScope.INFO, SwingUtil.createImageIcon("info.png"));
        }
        return icons;
    }

    public static EnumMap getColors() {
        if (colors == null) {
            colors = new EnumMap(NuitonValidatorScope.class);
            colors.put(NuitonValidatorScope.FATAL, Color.MAGENTA);
            colors.put(NuitonValidatorScope.ERROR, Color.RED);
            colors.put(NuitonValidatorScope.WARNING, Color.YELLOW);
            colors.put(NuitonValidatorScope.INFO, Color.GREEN);
        }
        return colors;
    }

    public static Color getColor(NuitonValidatorScope scope) {
        Color c = scope == null ? null : getColors().get(scope);
        return c;
    }

    public static ImageIcon getIcon(NuitonValidatorScope scope) {
        ImageIcon icon = scope == null ? null : getIcons().get(scope);
        return icon;
    }

    public static ImageIcon getFatalIcon() {
        return getIcons().get(NuitonValidatorScope.FATAL);
    }

    public static ImageIcon getErrorIcon() {
        return getIcons().get(NuitonValidatorScope.ERROR);
    }

    public static ImageIcon getWarningIcon() {
        return getIcons().get(NuitonValidatorScope.WARNING);
    }

    public static ImageIcon getInfoIcon() {
        return getIcons().get(NuitonValidatorScope.INFO);
    }

    protected SwingValidatorUtil() {
        // no instance
    }

    public static  SwingValidator newValidator(Class type,
                                                     String context) {

//        if (BeanValidatorFactory.isDefaultCreator()) {
//
//            // set the swing bean validator creator
//            BeanValidatorFactory.setCreator(new DefaultSwingValidatorCreator());
//        }
        SwingValidator validator =
                SwingValidator.newValidator(type, context);
        return validator;
    }

    /**
     * To install all the stuff for validation on a {@link JAXXValidator} ui.
     * 

* This method is called after validators has beeen detected in the ui (via * the method {@link #detectValidators(JAXXValidator)}).. *

* 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 inovked by a generated jaxx-validator file at the * end of the {@code $completeSetup} method. * * @param ui the validator ui to init. */ public static void installUI(JAXXValidator ui) { // first install fields with validation ui.registerValidatorFields(); // detectValidatorFields(ui); // for each validator install uis + reload bean List validatorIds = ui.getValidatorIds(); for (String validatorId : validatorIds) { SwingValidator validator = ui.getValidator(validatorId); // install uis validator.installUIs(); // reload attached bean (to see validation on uis) validator.reloadBean(); } } /** * Given a {@link JAXXValidator} ui, detects on it all the validators it * contains. *

* A validator is detected from the annotation {@link Validator} placed on * his field. *

* This method is always inovked by a generated jaxx-validator file at the * end of the {@code $completeSetup} method. * * @param ui the ui where to seek for validators. * @return the list of ids of validators found on the given ui */ public static List detectValidators(JAXXValidator ui) { List validatorIds = new ArrayList(); Map validators = ReflectUtil.getFieldAnnotation( ui.getClass(), Validator.class, true ); for (Map.Entry entry : validators.entrySet()) { Field field = entry.getKey(); Validator annotation = entry.getValue(); String validatorId = annotation.validatorId(); validatorIds.add(validatorId); if (log.isInfoEnabled()) { log.info("Detect validator [" + annotation.validatorId() + "] on field " + field.getName()); } } return Collections.unmodifiableList(validatorIds); } /** * Detects on a {@link JAXXValidator} ui all the validator fields it * contains. *

* A validator field is detected via the annotation placed on his field or * his getter (in cas of inheritance). *

* Each field found will be registred 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 ui the ui to seek */ public static void detectValidatorFields(JAXXValidator ui) { Multimap editors = getValidatorEditors(ui); try { for (String validatorId : ui.getValidatorIds()) { SwingValidator validator = ui.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) { if (log.isInfoEnabled()) { log.info("Detects for validator [" + validatorId + "] property " + propertyName + " for editor " + fieldAnnotation.editorName()); } validator.setFieldRepresentation(propertyName, editor); } } } } finally { editors.clear(); } } /** * Prepare the ui where to display the validators messages. * * @param errorTable the table where to display validators messages * @param render renderer to use */ public static void installUI(JTable errorTable, SwingValidatorMessageTableRenderer render) { errorTable.setDefaultRenderer(Object.class, render); errorTable.getRowSorter().setSortKeys( Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); SwingUtil.setI18nTableHeaderRenderer( errorTable, n_("validator.scope.header"), n_("validator.scope.header.tip"), n_("validator.field.header"), n_("validator.field.header.tip"), n_("validator.message.header"), n_("validator.message.header.tip")); // register a single 'goto widget error' mouse listener on errorTable registerErrorTableMouseListener(errorTable); SwingUtil.fixTableColumnWidth(errorTable, 0, 25); } /** * Prepare the ui where to display the validators messages. * * @param errorTable the table where to display simpleBean validators messages * @param render renderer to use * @since 2.6.23 */ public static void installUI(JTable errorTable, SimpleBeanValidatorMessageTableRenderer render) { errorTable.setDefaultRenderer(Object.class, render); errorTable.getRowSorter().setSortKeys( Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); SwingUtil.setI18nTableHeaderRenderer( errorTable, n_("validator.scope.header"), n_("validator.scope.header.tip"), n_("validator.field.header"), n_("validator.field.header.tip"), n_("validator.message.header"), n_("validator.message.header.tip")); SwingUtil.fixTableColumnWidth(errorTable, 0, 25); } /** * Prepare the ui where to display the validators messages. * * @param errorTable the table where to display validators messages * @param render renderer to use * @since 2.5.3 */ public static void installUI(JTable errorTable, SwingListValidatorMessageTableRenderer render) { errorTable.setDefaultRenderer(Object.class, render); errorTable.getRowSorter().setSortKeys( Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); SwingUtil.setI18nTableHeaderRenderer( errorTable, n_("validator.scope.header"), n_("validator.scope.header.tip"), n_("validator.bean.header"), n_("validator.bean.header.tip"), n_("validator.field.header"), n_("validator.field.header.tip"), n_("validator.message.header"), n_("validator.message.header.tip")); SwingUtil.fixTableColumnWidth(errorTable, 0, 25); } /** * Prepare the ui where to display the validators messages. * * @param errorTableModel * @param errorTable the table where to display validators messages * @since 2.5.3 */ public static void registerListValidator(BeanListValidator validator, SwingListValidatorMessageTableModel errorTableModel, JTable dataTable, JTable errorTable, SwingListValidatorDataLocator dataLocator) { // register the validator to the error table model errorTableModel.registerValidator(validator); // add click listener to go to cell errorTable.addMouseListener(new SwingListValidatorMessageTableMouseListener( dataTable, dataLocator )); // listen on editor model to add / remove bean into validator dataTable.getModel().addTableModelListener( new SwingListValidatorTableEditorModelListener(validator, dataLocator)); } /** * Add hightlighters on the editor of beans. * * @param validator the validator where to find bean states * @param editor the editor of beans * @param dataLocator the data locator * @param scopes scopes to hightlight * @param type of bean to validate * @since 2.5.3 */ public static void addHightLighterOnEditor(BeanListValidator validator, JXTable editor, SwingListValidatorDataLocator dataLocator, NuitonValidatorScope... scopes) { for (NuitonValidatorScope scope : scopes) { SwingListValidatorHighlightPredicate predicate = SwingListValidatorHighlightPredicate.newPredicate( scope, validator, dataLocator ); ColorHighlighter highlighter = new ColorHighlighter(predicate); highlighter.setBackground(SwingValidatorUtil.getColor(scope)); editor.addHighlighter(highlighter); } } /** * Register for a given validator list ui a validator mouse listener. *

* Note: there is only one listener registred for a given list model, so * invoking this method tiwce or more will have no effect. * * @param list the validation ui list * @return the listener instanciate or found * @see SwingValidatorMessageListMouseListener */ public static SwingValidatorMessageListMouseListener registerErrorListMouseListener(JList list) { SwingValidatorMessageListMouseListener listener = getErrorListMouseListener(list); if (listener != null) { return listener; } listener = new SwingValidatorMessageListMouseListener(); if (log.isDebugEnabled()) { log.debug(listener.toString()); } list.addMouseListener(listener); return listener; } /** * Register for a given validator table ui a validator mouse listener *

* Note: there is onlt one listener registred for a givne table model, so * invokin this method twice or more will have no effect. * * @param table the validator table ui * @return the listener instanciate or found * @see SwingValidatorMessageTableMouseListener */ public static SwingValidatorMessageTableMouseListener registerErrorTableMouseListener(JTable table) { SwingValidatorMessageTableMouseListener listener = getErrorTableMouseListener(table); if (listener != null) { return listener; } listener = new SwingValidatorMessageTableMouseListener(); if (log.isDebugEnabled()) { log.debug(listener.toString()); } table.addMouseListener(listener); return listener; } /** * @param list the validator list ui * @return the validator list mouse listener, or null if not * found * @see SwingValidatorMessageListMouseListener */ public static SwingValidatorMessageListMouseListener getErrorListMouseListener(JList list) { if (list != null) { for (MouseListener listener : list.getMouseListeners()) { if (listener instanceof SwingValidatorMessageListMouseListener) { return (SwingValidatorMessageListMouseListener) listener; } } } return null; } /** * @param table the validator table ui * @return the validator table mouse listener, or null if not * found * @see SwingValidatorMessageTableMouseListener */ public static SwingValidatorMessageTableMouseListener getErrorTableMouseListener(JTable table) { if (table != null) { for (MouseListener listener : table.getMouseListeners()) { if (listener instanceof SwingValidatorMessageTableMouseListener) { return (SwingValidatorMessageTableMouseListener) listener; } } } return null; } /** * @param table the validator table ui * @return the validator table mouse listener, or null if not * found * @see SwingValidatorMessageTableMouseListener */ public static SwingValidatorMessageTableMouseListener getListErrorTableMouseListener(JTable table) { if (table != null) { for (MouseListener listener : table.getMouseListeners()) { if (listener instanceof SwingValidatorMessageTableMouseListener) { return (SwingValidatorMessageTableMouseListener) listener; } } } return null; } public static String getMessage(SwingValidatorMessage model) { String text = model.getMessage(); if (model.getField() != null) { text = model.getI18nError(text); } return text; } public static String getMessage(SimpleBeanValidatorMessage model) { String text = model.getMessage(); if (model.getField() != null) { text = model.getI18nError(text); } return text; } public static String getMessage(SwingListValidatorMessage model) { String text = model.getMessage(); if (model.getField() != null) { text = model.getI18nError(text); } return text; } public static String getFieldName(SwingValidatorMessage model, String value) { String text = null; JComponent editor = model.getEditor(); if (editor != null) { text = (String) editor.getClientProperty("validatorLabel"); /*if (l != null) { text = I18n._(l); } else { // TODO should try the text }*/ } if (text == null) { text = value; } return text; } public static String getFieldName(SwingListValidatorMessage model, String value) { String text = null; JComponent editor = model.getEditor(); if (editor != null) { text = (String) editor.getClientProperty("validatorLabel"); /*if (l != null) { text = I18n._(l); } else { // TODO should try the text }*/ } if (text == null) { text = value; } return text; } /** * Method to listen the modification of the context name and at each time * reload fields of the ui. * * @param validator validator to listen * @param ui ui to refresh when context name has changed * @since 2.2.1 */ public static void listenValidatorContextNameAndRefreshFields( SwingValidator validator, final JAXXValidator ui) { PropertyChangeListener listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { SwingValidator validator = (SwingValidator) evt.getSource(); if (log.isInfoEnabled()) { log.info("Context name changed to [" + evt.getNewValue() + "] for validator " + validator.getType()); } ui.registerValidatorFields(); } }; validator.addPropertyChangeListener( SwingValidator.CONTEXT_PROPERTY, listener ); } // /** // * Default bean validator creator to use in the {@link BeanValidatorFactory}. // * // * @author tchemit // * @since 2.1 // */ // public static class DefaultSwingValidatorCreator implements BeanValidatorFactory.BeanValidatorCreator { // // @Override // public BeanValidator newBeanValidator(NuitonValidatorProvider provider, Class type, String context, NuitonValidatorScope... scopes) { // BeanValidator beanValidator = new SwingValidator(provider, // type, // context, // scopes // ); // return beanValidator; // } // } /** * Convinient method to attach a bean to all validators of an JAXXObject. *

* It is possible to exclude some validator to be treated. * * @param ui the ui containing the validatros to treate * @param bean the bean to attach in validators (can be null) * @param excludeIds the list of validator id to exclude */ @SuppressWarnings({"unchecked"}) public static void setValidatorBean(JAXXObject ui, Object bean, String... excludeIds) { if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { return; } JAXXValidator jaxxValidator = (JAXXValidator) ui; List validatorIds = jaxxValidator.getValidatorIds(); if (excludeIds.length > 0) { validatorIds = new ArrayList(validatorIds); for (String excludeId : excludeIds) { validatorIds.remove(excludeId); } } for (String validatorId : validatorIds) { SwingValidator beanValidator = jaxxValidator.getValidator(validatorId); if (bean == null || beanValidator.getType().isAssignableFrom( bean.getClass())) { // touch validator, only if fits the bean type (or bean is null) beanValidator.setBean(bean); } } } /** * Convinient method to set the changed property to all validators of an * JAXXObject. *

* It is possible to exclude some validator to be treated. * * @param ui the ui containing the validatros to treate * @param newValue the new value to set in changed validator property * @param excludeIds the list of validator id to exclude */ @SuppressWarnings({"unchecked"}) public static void setValidatorChanged(JAXXObject ui, boolean newValue, String... excludeIds) { if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { return; } JAXXValidator jaxxValidator = (JAXXValidator) ui; List validatorIds = jaxxValidator.getValidatorIds(); if (excludeIds.length > 0) { validatorIds = new ArrayList(validatorIds); for (String excludeId : excludeIds) { validatorIds.remove(excludeId); } } for (String validatorId : validatorIds) { SwingValidator beanValidator = jaxxValidator.getValidator(validatorId); beanValidator.setChanged(newValue); } } protected static Multimap getValidatorEditors(JAXXValidator ui) { Multimap editors = ArrayListMultimap.create(); Map validatorFields = null; Map validatorMethods = null; try { validatorFields = ReflectUtil.getFieldAnnotation( ui.getClass(), ValidatorField.class, true ); validatorMethods = ReflectUtil.getMethodAnnotation( ui.getClass(), ValidatorField.class, true ); for (Map.Entry fieldEntry : validatorFields.entrySet()) { Field field = fieldEntry.getKey(); field.setAccessible(true); ValidatorField fieldAnnotation = fieldEntry.getValue(); JComponent editor = (JComponent) field.get(ui); editors.put(editor, fieldAnnotation); } for (Map.Entry fieldEntry : validatorMethods.entrySet()) { Method method = fieldEntry.getKey(); method.setAccessible(true); ValidatorField fieldAnnotation = fieldEntry.getValue(); JComponent editor = (JComponent) method.invoke(ui); editors.put(editor, fieldAnnotation); } } catch (Exception e) { throw new IllegalStateException("Could not init validators on ui " + ui, e); } finally { if (validatorFields != null) { validatorFields.clear(); } if (validatorMethods != null) { validatorMethods.clear(); } } return editors; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy