Author: tchemit Date: 2008-10-17 19:44:04 +0000 (Fri, 17 Oct 2008) New Revision: 957 Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorError.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorErrorListModel.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java Log: introduce Error model Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java 2008-10-17 17:34:35 UTC (rev 956) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java 2008-10-17 19:44:04 UTC (rev 957) @@ -21,6 +21,7 @@ import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ValidationAware; import com.opensymphony.xwork2.ValidationAwareSupport; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationManager; @@ -35,13 +36,10 @@ import org.jdesktop.jxlayer.plaf.AbstractLayerUI; import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; import javax.swing.JComponent; -import javax.swing.JList; import javax.swing.SwingUtilities; import java.awt.AlphaComposite; import java.awt.Color; -import java.awt.Component; import java.awt.Container; import java.awt.Graphics2D; import java.awt.Insets; @@ -52,10 +50,8 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Enumeration; +import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -157,11 +153,8 @@ /** permet de faire le lien en un champs du bean et l'objet qui permet de l'editer */ protected Map<String, JComponent> fieldRepresentation; - /** Objet servant a afficher toutes les erreurs */ - protected JList errorList = null; - /** Object servant a contenir la liste des erreurs */ - protected DefaultListModel errorListModel; + protected BeanValidatorErrorListModel errorListModel; public BeanValidator() { pcs = new PropertyChangeSupport(this); @@ -170,25 +163,15 @@ fieldRepresentation = new HashMap<String, JComponent>(); } - /** - * Permet de modifier l'objet permettant d'afficher toutes les errors - * - * @param errorList si null arrete d'afficher les errors - */ - public void setErrorList(JList errorList) { - this.errorList = errorList; - } - - public JList getErrorList() { - return errorList; - } - - public DefaultListModel getErrorListModel() { + public BeanValidatorErrorListModel getErrorListModel() { return errorListModel; } - public void setErrorListModel(DefaultListModel errorListModel) { + public void setErrorListModel(BeanValidatorErrorListModel errorListModel) { this.errorListModel = errorListModel; + if (errorListModel != null) { + errorListModel.registerValidator(this); + } } /** @@ -261,6 +244,18 @@ pcs.firePropertyChange("bean", oldBean, bean); } + public Map getFieldErrors() { + return validationContext.getFieldErrors(); + } + + public Collection getActionErrors() { + return validationContext.getActionErrors(); + } + + public Collection getActionMessages() { + return validationContext.getActionMessages(); + } + /** install layers on required components */ public void installLayers() { SwingUtilities.invokeLater(new Runnable() { @@ -308,23 +303,7 @@ } try { - List<String> newErrors = new ArrayList<String>(); - Enumeration enumeration = getErrorListModel().elements(); - while (enumeration.hasMoreElements()) { - Object o = enumeration.nextElement(); - newErrors.add((String) o); - } - for (Object o : validationContext.getFieldErrors().entrySet()) { - Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; - String field = (String) r.getKey(); - List<String> errors = (List<String>) r.getValue(); - JComponent component = fieldRepresentation.get(field); - for (String error : errors) { - newErrors.remove(component.getName() + " : " + error); - } - } - validationSupport.clearErrorsAndMessages(); getValidator().validate(bean, null, validationContext); @@ -337,21 +316,9 @@ log.info(this + " : " + validationContext.getFieldErrors()); - for (Object o : validationContext.getFieldErrors().entrySet()) { - Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; - String field = (String) r.getKey(); - List<String> errors = (List<String>) r.getValue(); - JComponent component = fieldRepresentation.get(field); - for (String error : errors) { - newErrors.add(component.getName() + " : " + error); - } - } + // add errors + errorListModel.addErrors(this); - getErrorListModel().clear(); - for (String newError : newErrors) { - getErrorListModel().addElement(newError); - } - for (String fieldname : fieldRepresentation.keySet()) { JComponent c = fieldRepresentation.get(fieldname); //todo: a supprimer mais actuellemnt le layer ne se repaint pas bien, cela n'est pas normal @@ -377,7 +344,7 @@ Container container = c.getParent(); if (container instanceof JXLayer) { IconValidationUI ui = new IconValidationUI(fieldname, c.getName(), validationSupport); - // TranslucentValidationUI ui = new TranslucentValidationUI(fieldname, validationSupport.getFieldErrors()); + //TranslucentValidationUI ui = new TranslucentValidationUI(fieldname, c.getName(), validationSupport); ui.setEnabled(true); JXLayer<JComponent> jx = (JXLayer<JComponent>) container; jx.setUI(ui); @@ -389,20 +356,46 @@ protected class Listener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { + // only validate if the property has really changed... + Object oldValue = evt.getOldValue(); + Object newValue = evt.getNewValue(); + if (oldValue == null && newValue == null) { + return; + } + if ((oldValue != null && oldValue.equals(newValue)) || (newValue != null && newValue.equals(oldValue))) { + return; + } + if (log.isDebugEnabled()) { + log.debug("launch validation from event [name:" + evt.getPropertyName() + " <old:" + oldValue + ", new:" + newValue + ">]"); + } validate(); setChanged(true); } } + /** @return <code>true</code> if errors are detected, <code>false</code> otherwise */ + public boolean hasErrors() { + //todo should also detecte actionErrors ? + return validationContext.hasFieldErrors(); + //return validationContext.hasFieldErrors() || validationContext.hasActionErrors(); + } public static class TranslucentValidationUI extends AbstractLayerUI<JComponent> { - protected String field = null; - protected Map resultValidation = null; + /** bean field */ + protected String field; - public TranslucentValidationUI(String field, Map resultValidation) { + /** component id */ + protected String componentId; + + /** validation context */ + protected ValidationAware validationContext; + + public TranslucentValidationUI(String field, String componentId, ValidationAware validationContext) { this.field = field; - this.resultValidation = resultValidation; + this.componentId = componentId; + this.validationContext = validationContext; + log.info("install " + this + "<field:" + field + ", componentId:" + componentId + ">"); } @Override @@ -421,7 +414,7 @@ view.getWidth() - insets.left - insets.right, view.getHeight() - insets.top - insets.bottom)); - g2.setColor(!resultValidation.containsKey(field) ? + g2.setColor(!validationContext.getFieldErrors().containsKey(field) ? Color.GREEN : Color.RED); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); g2.fillRect(0, 0, l.getWidth(), l.getHeight()); @@ -449,16 +442,18 @@ } /** bean validation field */ - protected String field = null; + protected String field; /** component id */ - protected String componentId = null; - protected ValidationAwareSupport resultValidation = null; + protected String componentId; - public IconValidationUI(String field, String componentId, ValidationAwareSupport resultValidation) { + /** validation context */ + protected ValidationAware validationContext; + + public IconValidationUI(String field, String componentId, ValidationAware validationContext) { this.field = field; - this.resultValidation = resultValidation; this.componentId = componentId; + this.validationContext = validationContext; log.info("install " + this + "<field:" + field + ", componentId:" + componentId + ">"); } @@ -477,14 +472,13 @@ @Override protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) { super.paintLayer(g2, l); - Component component = l.getComponent(1); // There is no need to take insets into account for this painter - if (resultValidation.getFieldErrors().containsKey(field)) { - log.info("requiredId : " + componentId + " : componentName : " + component.getName()); + if (validationContext.getFieldErrors().containsKey(field)) { g2.drawImage(INVALID_ICON, l.getWidth() - INVALID_ICON.getWidth() - 1, 0, null); // g2.drawImage(INVALID_ICON, 0, 0, null); } } } + } Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorError.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorError.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorError.java 2008-10-17 19:44:04 UTC (rev 957) @@ -0,0 +1,83 @@ +package jaxx.runtime; + +import org.codelutin.i18n.I18n; + +import javax.swing.JComponent; + +/** + * The model of an error. + * + * @author chemit + */ +public class BeanValidatorError<T> { + + protected BeanValidator<T> validator; + + protected String fieldName; + + protected String error; + + protected JComponent component; + + public BeanValidator<T> getValidator() { + return validator; + } + + public String getFieldName() { + return fieldName; + } + + public String getError() { + return error; + } + + public JComponent getComponent() { + return component; + } + + public void setValidator(BeanValidator<T> validator) { + this.validator = validator; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public void setError(String error) { + this.error = error; + } + + public void setComponent(JComponent component) { + this.component = component; + } + + @Override + public String toString() { + return component.getName() + " : " + I18n._(error); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BeanValidatorError)) { + return false; + } + + BeanValidatorError that = (BeanValidatorError) o; + + return component.equals(that.component) && error.equals(that.error) && fieldName.equals(that.fieldName) && validator.equals(that.validator); + + } + + @Override + public int hashCode() { + int result; + result = validator.hashCode(); + result = 31 * result + fieldName.hashCode(); + result = 31 * result + error.hashCode(); + result = 31 * result + component.hashCode(); + return result; + } +} Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorErrorListModel.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorErrorListModel.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidatorErrorListModel.java 2008-10-17 19:44:04 UTC (rev 957) @@ -0,0 +1,138 @@ +package jaxx.runtime; + +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; + +/** + * The model of the list of errors + * + * @author chemit + */ +public class BeanValidatorErrorListModel extends DefaultListModel { + private static final long serialVersionUID = 1L; + + /** list of registred validators */ + protected transient List<BeanValidator<?>> validators; + + /** comporatorof errors */ + protected transient Comparator<BeanValidatorError> comparator; + + public BeanValidatorErrorListModel() { + validators = new ArrayList<BeanValidator<?>>(); + } + + public void registerValidator(BeanValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException("the validator " + validator + " is already registred in " + this); + } + validators.add(validator); + } + + public <T> void addErrors(BeanValidator<T> validator) { + if (!validators.contains(validator)) { + throw new IllegalArgumentException("the validator " + validator + " is not registred in " + this); + } + + // new errors for the given validator + List<BeanValidatorError> newErrors = new ArrayList<BeanValidatorError>(); + // old errors for the given validator + List<BeanValidatorError> oldErrors = new ArrayList<BeanValidatorError>(); + // old errors for other validators + List<BeanValidatorError> oldOtherErrors = new ArrayList<BeanValidatorError>(); + + // split old errors from other validators + splitOldErrors(validator, oldErrors, oldOtherErrors); + + // fill new errors + fillNewErrors(validator, newErrors); + + // check if something has changed for the given validator + if (hasChanged(oldErrors, newErrors)) { + + // reinject other errors + newErrors.addAll(oldOtherErrors); + + // sort errors + Collections.sort(newErrors, getComparator()); + + // clean errors in model + clear(); + + // reinject in list model, all the errors + for (BeanValidatorError error : newErrors) { + addElement(error); + } + + // notify thaht the model has changed + fireContentsChanged(this, 0, getSize() - 1); + } + } + + protected boolean hasChanged(List<BeanValidatorError> oldErrors, List<BeanValidatorError> newErrors) { + if (oldErrors.size() != newErrors.size()) { + return true; + } + for (BeanValidatorError oldError : oldErrors) { + if (!newErrors.contains(oldError)) { + return true; + } + } + return false; + } + + protected <T> void fillNewErrors(BeanValidator<T> validator, List<BeanValidatorError> newErrors) { + if (validator.hasErrors()) { + // inject this validator errors + for (Object o : validator.getFieldErrors().entrySet()) { + Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; + BeanValidatorError<T> error; + String field = (String) r.getKey(); + + JComponent component = validator.getFieldRepresentation(field); + for (Object errorString : (List<?>) r.getValue()) { + String error1 = (String) errorString; + error = new BeanValidatorError<T>(); + error.setComponent(component); + error.setValidator(validator); + error.setError(error1); + error.setFieldName(field); + newErrors.add(error); + } + } + //todo should also do actionErrors + } + } + + protected <T> void splitOldErrors(BeanValidator<T> validator, List<BeanValidatorError> oldErrors, List<BeanValidatorError> oldOtherErrors) { + Enumeration enumeration = elements(); + + while (enumeration.hasMoreElements()) { + Object o = enumeration.nextElement(); + BeanValidatorError<?> error = (BeanValidatorError) o; + if (!error.getValidator().equals(validator)) { + // error from another validator, keep it + oldOtherErrors.add(error); + } else { + oldErrors.add(error); + } + } + } + + protected Comparator<BeanValidatorError> getComparator() { + if (comparator == null) { + comparator = new Comparator<BeanValidatorError>() { + public int compare(BeanValidatorError o1, BeanValidatorError o2) { + return o1.toString().compareTo(o2.toString()); + } + }; + } + return comparator; + } + +}
participants (1)
-
tchemit@users.labs.libre-entreprise.org