Author: chemit Date: 2008-12-01 02:50:26 +0000 (Mon, 01 Dec 2008) New Revision: 1042 Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidationTableRenderer.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java lutinjaxx/trunk/jaxx-core/src/main/resources/icons/ lutinjaxx/trunk/jaxx-core/src/main/resources/icons/error.png lutinjaxx/trunk/jaxx-core/src/main/resources/icons/warning.png lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java Modified: lutinjaxx/trunk/jaxx-core/changelog lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx Log: introduce scope in BeanValidator (ERROR or WARNING) Modified: lutinjaxx/trunk/jaxx-core/changelog =================================================================== --- lutinjaxx/trunk/jaxx-core/changelog 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/changelog 2008-12-01 02:50:26 UTC (rev 1042) @@ -1,4 +1,8 @@ - 0.6 chemit 200811?? + 0.7 chemit + * 20081201 [chemit] introduce scope in BeanValidator (ERROR or WARNING) + * 20081201 [chemit] only enter once in $initialize method in generated code + + 0.6 chemit 200811 * 20081118 [chemit] introduce NavigationUtil, save in context selected node * 20081107 [chemit] improve data binding and code generation : - make possible inheritance in binding Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -17,6 +17,8 @@ import jaxx.types.InsetsConverter; import jaxx.types.PrimitiveConverter; import jaxx.types.TypeManager; +import jaxx.types.BeanValidatorScopeConverter; +import jaxx.runtime.validator.BeanValidator.Scope; import java.awt.Color; import java.awt.Component; @@ -55,5 +57,7 @@ TypeManager.registerTypeConverter(Color.class, new ColorConverter()); TypeManager.registerTypeConverter(GridBagConstraints.class, new GridBagConstraintsConverter()); TypeManager.registerTypeConverter(Insets.class, new InsetsConverter()); + + TypeManager.registerTypeConverter(Scope.class, new BeanValidatorScopeConverter()); } } \ No newline at end of file Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -2,12 +2,14 @@ import jaxx.runtime.validator.BeanValidator; import jaxx.runtime.validator.ErrorListMouseListener; +import jaxx.runtime.validator.ErrorTableMouseListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdesktop.jxlayer.JXLayer; import javax.swing.JComponent; import javax.swing.JList; +import javax.swing.JTable; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; @@ -397,6 +399,20 @@ list.addMouseListener(new ErrorListMouseListener()); } + public static void registerErrorTableMouseListener(JTable table) { + if (table == null) { + return; + } + for (MouseListener listener : table.getMouseListeners()) { + if (listener instanceof ErrorTableMouseListener) { + // already have a such listener + log.info("already registered a such MouseListener : " + listener); + return; + } + } + table.addMouseListener(new ErrorTableMouseListener()); + } + /** * Compute the string representation of an object. * <p/> Added: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidationTableRenderer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidationTableRenderer.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidationTableRenderer.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -0,0 +1,59 @@ +package jaxx.runtime.validator; + +import jaxx.runtime.swing.Utils; +import jaxx.runtime.validator.BeanValidator.Scope; +import static org.codelutin.i18n.I18n._; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +/** @author chemit */ +public class BeanValidationTableRenderer extends DefaultTableCellRenderer { + + ImageIcon errorIcon; + ImageIcon warningIcon; + + public BeanValidationTableRenderer() { + errorIcon = Utils.createImageIcon("error.png"); + warningIcon = Utils.createImageIcon("warning.png"); + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel rendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + ImageIcon icon = null; + String text = null; + if (value instanceof Scope) { + + Scope scope = (Scope) value; + switch (scope) { + case ERROR: + icon = errorIcon; + break; + case WARNING: + icon = warningIcon; + break; + } + //todo fix size of scope column + /*rendererComponent.setSize(16,rendererComponent.getHeight()); + rendererComponent.setMaximumSize(new Dimension(16,rendererComponent.getHeight())); + rendererComponent.setPreferredSize(new Dimension(16,rendererComponent.getHeight()));*/ + } else if (value instanceof BeanValidatorError) { + text = _(((BeanValidatorError) value).getError()); + } else { + // keep text rendered + text = rendererComponent.getText(); + } + rendererComponent.setText(text); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + @Override + protected void setValue(Object value) { + super.setValue(value); + } +} Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -135,6 +135,17 @@ */ public class BeanValidator<T> { + /** + * Pour definir le niveau de validation. + * <p/> + * Par défaut, le validateur est supposé géré des erreurs, mais on peut aussi l'utiliser + * pour consigner des warnings sur le bean surveiller. + */ + public enum Scope { + ERROR, + WARNING + } + static public final String BEAN_PROERTY = "bean"; private static final String CONTEXT_NAME_PROPERTY = "contextName"; @@ -176,6 +187,9 @@ /** Object servant a contenir la liste des erreurs */ protected BeanValidatorErrorListModel errorListModel; + /** Object servant a contenir la liste des erreurs */ + protected BeanValidatorErrorTableModel errorTableModel; + /** ui renderer class */ protected Class<? extends AbstractBeanValidatorUI> uiClass; @@ -188,6 +202,7 @@ /** the validation named context */ protected String contextName; + protected Scope scope = Scope.ERROR; public BeanValidator() { pcs = new PropertyChangeSupport(this); @@ -197,18 +212,6 @@ conversionErrors = new TreeMap<String, String>(); l = new 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(); setValid(!hasErrors()); setChanged(true); @@ -236,10 +239,18 @@ return errorListModel; } + public BeanValidatorErrorTableModel getErrorTableModel() { + return errorTableModel; + } + public JComponent getFieldRepresentation(String fieldname) { return fieldRepresentation.get(fieldname); } + public Scope getScope() { + return scope; + } + /** * Retourne vrai si l'objet bean a ete modifie depuis le dernier * {@link #setBean} @@ -286,6 +297,14 @@ } } + public void setErrorTableModel(BeanValidatorErrorTableModel errorTableModel) { + this.errorTableModel = errorTableModel; + if (errorTableModel != null) { + // register the validator in the model table + errorTableModel.registerValidator(this); + } + } + /** * Permet d'indiquer le composant graphique responsable de l'affichage * d'un attribut du bean @@ -351,7 +370,7 @@ } else { // must remove all errors from this validator on errorListModel validationSupport.clearErrorsAndMessages(); - errorListModel.addErrors(this); + addErrors(); } setValid(!hasErrors()); setChanged(false); @@ -368,10 +387,14 @@ this.uiClass = uiClass; } + public void setScope(Scope scope) { + this.scope = scope; + } + /** @return <code>true</code> if errors are detected, <code>false</code> otherwise */ public boolean hasErrors() { //todo should also detecte actionErrors ? - return validationContext.hasFieldErrors() || !conversionErrors.isEmpty(); + return scope == Scope.ERROR && (validationContext.hasFieldErrors() || !conversionErrors.isEmpty()); //return validationContext.hasFieldErrors() || validationContext.hasActionErrors(); } @@ -479,7 +502,7 @@ log.debug(this + " : " + validationContext.getFieldErrors()); } // add errors - errorListModel.addErrors(this); + addErrors(); for (String fieldname : fieldRepresentation.keySet()) { JComponent c = fieldRepresentation.get(fieldname); @@ -493,9 +516,9 @@ } } - /** @return <code>true</code> if validation is active, <code>false</code> otherwise. */ + /** @return <code>true</code> if validation is not active , <code>false</code> otherwise. */ protected boolean checkState() { - return bean == null || getErrorListModel() == null || fieldRepresentation.size() == 0; + return bean == null || (getErrorListModel() == null && getErrorTableModel() == null) || fieldRepresentation.size() == 0; } protected ActionValidatorManager getValidator() { @@ -565,4 +588,13 @@ validationContext.setFieldErrors(map); } + protected void addErrors() { + if (errorListModel != null) { + errorListModel.addErrors(this); + } + if (errorTableModel != null) { + errorTableModel.addErrors(this); + } + } + } Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -4,6 +4,8 @@ import javax.swing.JComponent; +import jaxx.runtime.validator.BeanValidator.Scope; + /** * The model of an error. * @@ -51,6 +53,10 @@ this.component = component; } + public Scope getScope() { + return validator.getScope(); + } + @Override public String toString() { return component.getName() + " : " + I18n._(error); Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -20,7 +20,7 @@ /** list of registred validators */ protected transient List<BeanValidator<?>> validators; - /** comporatorof errors */ + /** comporator of errors */ protected transient Comparator<BeanValidatorError> comparator; public BeanValidatorErrorListModel() { @@ -128,7 +128,7 @@ protected Comparator<BeanValidatorError> getComparator() { if (comparator == null) { comparator = new Comparator<BeanValidatorError>() { - public int compare(BeanValidatorError o1, BeanValidatorError o2) { + public int compare(BeanValidatorError o1, BeanValidatorError o2) { return o1.toString().compareTo(o2.toString()); } }; Copied: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java (from rev 1003, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -0,0 +1,164 @@ +package jaxx.runtime.validator; + +import jaxx.runtime.validator.BeanValidator.Scope; + +import javax.swing.JComponent; +import javax.swing.table.DefaultTableModel; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +/** + * The model of the list of errors + * + * @author chemit + */ +public class BeanValidatorErrorTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + public static final String[] columnNames = {"validator.scope", "validator.field", "validator.message"}; + + /** list of registred validators */ + protected transient List<BeanValidator<?>> validators; + + /** comporator of errors */ + protected transient Comparator<BeanValidatorError> comparator; + + public BeanValidatorErrorTableModel() { + super(columnNames, 0); + validators = new ArrayList<BeanValidator<?>>(); + } + + public int getErrorColumn() { + return findColumn(BeanValidatorErrorTableModel.columnNames[2]); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + 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 + getDataVector().clear(); + Scope scope = validator.getScope(); + // reinject in list model, all the errors + for (BeanValidatorError error : newErrors) { + addRow(new Object[]{scope, error.getFieldName(), error}); + } + + // notify thaht the model has changed + fireTableDataChanged(); + } + } + + 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); + if (component != null) { + 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) { + + int col = getErrorColumn(); + for (Object o : super.getDataVector()) { + Vector row = (Vector) o; + BeanValidatorError<?> error = (BeanValidatorError<?>) row.get(col); + 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) { + // first sort on scope + int scope = o1.getScope().ordinal() - o2.getScope().ordinal(); + if (scope != 0) { + return scope; + } + int field = o1.getFieldName().compareTo(o2.getFieldName()); + if (field != 0) { + return field; + } + return o1.getError().compareTo(o2.getError()); + } + }; + } + return comparator; + } + +} \ No newline at end of file Property changes on: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java ___________________________________________________________________ Name: svn:mergeinfo + Copied: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -0,0 +1,62 @@ +package jaxx.runtime.validator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * A mouse listener to put on a {@link javax.swing.JList} with a {@link jaxx.runtime.validator.BeanValidatorErrorListModel} as a model. + * <p/> + * When a double click occurs, find the selected error in model and then focus to the associated component of error. + * + * @author chemit + */ +public class ErrorTableMouseListener extends MouseAdapter { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(ErrorTableMouseListener.class); + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + BeanValidatorError<?> entry = getSelectedError(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getComponent(); + if (component != null) { + component.requestFocus(); + } + } + } + + + protected BeanValidatorError<?> getSelectedError(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof BeanValidatorErrorTableModel)) { + log.warn("model must be a " + BeanValidatorErrorTableModel.class + ", but was " + table.getModel()); + return null; + } + + BeanValidatorErrorTableModel model = (BeanValidatorErrorTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + int col = model.getErrorColumn(); + BeanValidatorError<?> entry = (BeanValidatorError) model.getValueAt(index, col); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + +} \ No newline at end of file Property changes on: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java ___________________________________________________________________ Name: svn:mergeinfo + Modified: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -13,6 +13,7 @@ import jaxx.reflect.ClassDescriptorLoader; import jaxx.runtime.Util; import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; import jaxx.runtime.validator.ui.AbstractBeanValidatorUI; import jaxx.tags.DefaultObjectHandler; import jaxx.types.TypeManager; @@ -34,9 +35,15 @@ public static final String BEAN_INITIALIZER_ATTRIBUTE = "beanInitializer"; public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; + public static final String ERROR_TABLE_MODEL_ATTRIBUTE = "errorTableModel"; public static final String ERROR_LIST_ATTRIBUTE = "errorList"; + public static final String ERROR_TABLE_ATTRIBUTE = "errorTable"; + public static final String ERROR_LIST_MODEL_DEFAULT = "errors"; + public static final String ERROR_TABLE_MODEL_DEFAULT = "errors2"; + public static final String ERROR_LIST_DEFAULT = "errorList"; + public static final String ERROR_TABLE_DEFAULT = "errorTable"; public static final String AUTOFIELD_ATTRIBUTE = "autoField"; public static final String UI_CLASS_ATTRIBUTE = "uiClass"; @@ -44,6 +51,8 @@ public static final String CONTEXT_NAME_ATTRIBUTE = "contextName"; + public static final String SCOPE_ATTRIBUTE = "scope"; + /** to use log facility, just put in your code: log.info(\"...\"); */ static Log log = LogFactory.getLog(BeanValidatorHandler.class); @@ -83,6 +92,14 @@ } if (!error) { + error = info.addErrorTableModel(tag, this, compiler); + } + + if (!error) { + error = info.addErrorTable(tag, compiler); + } + + if (!error) { error = info.addUiClass(this, compiler); } @@ -94,6 +111,10 @@ error = info.addContextName(this, compiler); } + if (!error) { + error = info.addScope(this, compiler); + } + if (error) { log.warn("error were detected in second compile pass of CompiledObject [" + info + "]"); } @@ -128,13 +149,15 @@ protected String bean; protected String beanClass; protected String contextName; - //protected String beanInitializer; protected String uiClass; protected String errorListModel; protected String errorList; protected Boolean autoField; protected Boolean strictMode; protected JAXXBeanInfo beanDescriptor; + protected String errorTableModel; + protected String errorTable; + protected Scope scope; public CompiledBeanValidator(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { super(id, objectClass, compiler); @@ -158,24 +181,20 @@ } return; } + if (CONTEXT_NAME_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { contextName = value.trim(); } return; } + if (BEAN_CLASS_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { beanClass = value.trim(); } return; } - /*if (BEAN_INITIALIZER_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - beanInitializer = value; - } - return; - }*/ if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { @@ -183,33 +202,56 @@ } return; } + if (ERROR_LIST_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { errorList = value.trim(); } return; } + + if (ERROR_TABLE_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTableModel = value.trim(); + } + return; + } + + if (ERROR_TABLE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTable = value.trim(); + } + return; + } + if (UI_CLASS_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { uiClass = value.trim(); } return; } + if (AUTOFIELD_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { - autoField = (Boolean) TypeManager.convertFromString(value.trim(), Boolean.class); } return; } + if (STRICT_MODE_ATTRIBUTE.equals(property)) { if (value != null && !value.trim().isEmpty()) { - strictMode = (Boolean) TypeManager.convertFromString(value.trim(), Boolean.class); } return; } + if (SCOPE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + scope = (Scope) TypeManager.convertFromString(value.trim(), Scope.class); + } + return; + } + throw new CompilerException("property " + property + " is not allowed on object " + this); //todo should not allowed to find other attributes @@ -244,6 +286,10 @@ return contextName; } + public Scope getScope() { + return scope; + } + public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { if (beanDescriptor == null && foundBean()) { @@ -324,6 +370,30 @@ } + protected boolean addErrorTableModel(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { + if (errorTableModel == null) { + // try with the default "errors" + if (!compiler.checkReference(tag, ERROR_TABLE_MODEL_DEFAULT, false, ERROR_LIST_MODEL_ATTRIBUTE)) { + return false; + } + errorTableModel = ERROR_TABLE_MODEL_DEFAULT; + } else { + if (errorTableModel.startsWith("{") && errorTableModel.endsWith("}")) { + // this is a script, no check here + errorTableModel = errorTableModel.substring(1, errorTableModel.length() - 1).trim(); + } else if (!compiler.checkReference(tag, errorTableModel, true, ERROR_TABLE_MODEL_ATTRIBUTE)) { + // errorListModel is not defined + return true; + } + } + + String code = handler.getSetPropertyCode(getJavaCode(), ERROR_TABLE_MODEL_ATTRIBUTE, errorTableModel, compiler); + appendAdditionCode(code); + + return false; + + } + protected boolean addContextName(BeanValidatorHandler handler, JAXXCompiler compiler) { if (contextName != null) { String code = handler.getSetPropertyCode(getJavaCode(), CONTEXT_NAME_ATTRIBUTE, TypeManager.getJavaCode(contextName), compiler); @@ -332,6 +402,14 @@ return false; } + protected boolean addScope(BeanValidatorHandler handler, JAXXCompiler compiler) { + if (scope != null) { + String code = handler.getSetPropertyCode(getJavaCode(), SCOPE_ATTRIBUTE, TypeManager.getJavaCode(scope), compiler); + appendAdditionCode(code); + } + return false; + } + protected boolean addErrorList(Element tag, JAXXCompiler compiler) { if (errorList == null) { @@ -353,6 +431,27 @@ } + protected boolean addErrorTable(Element tag, JAXXCompiler compiler) { + + if (errorTable == null) { + // try with the default "errorList" + if (!compiler.checkReference(tag, ERROR_TABLE_DEFAULT, false, ERROR_TABLE_ATTRIBUTE)) { + return false; + } + errorTable = ERROR_TABLE_DEFAULT; + } else { + if (!compiler.checkReference(tag, errorTable, true, ERROR_TABLE_ATTRIBUTE)) { + return true; + } + } + + String code = Util.class.getName() + ".registerErrorTableMouseListener(" + errorTable + ");"; + appendAdditionCode(code); + + return false; + + } + protected boolean addBean(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { if (!foundBean()) { @@ -368,7 +467,7 @@ // just has an intializer beanInitializer = bean.substring(1, bean.length() - 1); // this is not a real bean, so delete it - bean=null; + bean = null; } else { if (!compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { Copied: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -0,0 +1,29 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; + +public class BeanValidatorScopeConverter implements TypeConverter { + + public String getJavaCode(Object object) { + Scope type = (Scope) object; + return BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + type.name(); + } + + public Object convertFromString(String string, Class type) { + if (type != Scope.class) { + throw new IllegalArgumentException("unsupported type: " + type); + } + try { + return Scope.valueOf(string); + } catch (IllegalArgumentException e) { + // do nothing + } + + throw new IllegalArgumentException("unable to convert string '" + string + "' to " + Scope.class); + } +} \ No newline at end of file Property changes on: lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java ___________________________________________________________________ Name: svn:mergeinfo + Added: lutinjaxx/trunk/jaxx-core/src/main/resources/icons/error.png =================================================================== (Binary files differ) Property changes on: lutinjaxx/trunk/jaxx-core/src/main/resources/icons/error.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: lutinjaxx/trunk/jaxx-core/src/main/resources/icons/warning.png =================================================================== (Binary files differ) Property changes on: lutinjaxx/trunk/jaxx-core/src/main/resources/icons/warning.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Copied: lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java) =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java (rev 0) +++ lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java 2008-12-01 02:50:26 UTC (rev 1042) @@ -0,0 +1,46 @@ +package jaxx.junit; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; +import jaxx.types.BeanValidatorScopeConverter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class BeanValidatorScopeConverterTest { + + BeanValidatorScopeConverter converter; + Scope value; + String strValue; + + @Before + public void before() { + converter = new BeanValidatorScopeConverter(); + } + + @Test + public void testConvertFromString() { + value = (Scope) converter.convertFromString("ERROR", Scope.class); + Assert.assertEquals(value, Scope.ERROR); + + value = (Scope) converter.convertFromString("WARNING", Scope.class); + Assert.assertEquals(value, Scope.WARNING); + } + + @Test + public void testGetJavaCode() { + value = Scope.ERROR; + strValue = converter.getJavaCode(value); + Assert.assertEquals(BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + value.name(), strValue); + + value = Scope.WARNING; + strValue = converter.getJavaCode(value); + Assert.assertEquals(BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + value.name(), strValue); + } + + @Test(expected = IllegalArgumentException.class) + public void testConvertFromStringError() { + converter.convertFromString("FAKE", Scope.class); + } + +} \ No newline at end of file Property changes on: lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java ___________________________________________________________________ Name: svn:mergeinfo + Modified: lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx 2008-12-01 02:50:26 UTC (rev 1042) @@ -6,20 +6,24 @@ <Identity id='identity'/> <!-- errors model --> - <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors' onContentsChanged='ok.setEnabled(errors.size()==0)'/> + <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors' + onContentsChanged='ok.setEnabled(errors.size()==0)'/> <!-- validators --> - <BeanValidator id='validator' bean='model' errorListModel='errors'> + <BeanValidator id='validator' bean='model' errorListModel='errors' scope='ERROR'> <field name="text"/> <field name="text2"/> <field name="ratio"/> </BeanValidator> - <BeanValidator id='validator2' bean='model2' errorListModel='errors' uiClass="jaxx.runtime.validator.ui.IconValidationUI"> + <BeanValidator id='validator2' bean='model2' errorListModel='errors' + uiClass="jaxx.runtime.validator.ui.IconValidationUI" scope="WARNING"> <field name="text" component="_text"/> <field name="text2" component="_text2"/> <field name="ratio" component="_ratio"/> </BeanValidator> - <BeanValidator id='validator3' autoField='true' bean='identity' errorListModel='errors' uiClass="jaxx.runtime.validator.ui.TranslucentValidationUI"> + <BeanValidator id='validator3' autoField='true' bean='identity' errorListModel='errors' + uiClass="jaxx.runtime.validator.ui.TranslucentValidationUI" + scope='ERROR'> <field name="email" component="email2"/> </BeanValidator> @@ -34,8 +38,8 @@ <JLabel text='Text:'/> </cell> <cell weightx='1'> - <JTextField id='text' text='{model.getText()}' - onKeyReleased='model.setText(text.getText())'/> + <JTextField id='text' text='{model.getText()}' + onKeyReleased='model.setText(text.getText())'/> </cell> </row> <row> @@ -43,8 +47,8 @@ <JLabel text='Text2:'/> </cell> <cell weightx='1'> - <JTextField id='text2' text='{model.getText2()}' - onKeyReleased='model.setText2(text2.getText())'/> + <JTextField id='text2' text='{model.getText2()}' + onKeyReleased='model.setText2(text2.getText())'/> </cell> </row> @@ -53,8 +57,8 @@ <JLabel text='Ratio:'/> </cell> <cell> - <JSlider id='ratio' minimum='0' maximum='100' value='{model.getRatio()}' - onStateChanged='model.setRatio(ratio.getValue())'/> + <JSlider id='ratio' minimum='0' maximum='100' value='{model.getRatio()}' + onStateChanged='model.setRatio(ratio.getValue())'/> </cell> </row> </Table> @@ -62,8 +66,8 @@ </cell> <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> <JPanel border='{BorderFactory.createTitledBorder("Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> <row> <cell> <JLabel text='Text:'/> @@ -89,7 +93,7 @@ <JLabel text='{model.getRatio()}'/> </cell> </row> - </Table> + </Table> </JPanel> </cell> </row> @@ -103,8 +107,8 @@ <JLabel text='Text:'/> </cell> <cell weightx='1'> - <JTextField id='_text' text='{model2.getText()}' - onKeyReleased='model2.setText(_text.getText())'/> + <JTextField id='_text' text='{model2.getText()}' + onKeyReleased='model2.setText(_text.getText())'/> </cell> </row> <row> @@ -112,8 +116,8 @@ <JLabel text='Text2:'/> </cell> <cell weightx='1'> - <JTextField id='_text2' text='{model2.getText2()}' - onKeyReleased='model2.setText2(_text2.getText())'/> + <JTextField id='_text2' text='{model2.getText2()}' + onKeyReleased='model2.setText2(_text2.getText())'/> </cell> </row> @@ -122,8 +126,8 @@ <JLabel text='Ratio:'/> </cell> <cell> - <JSlider id='_ratio' minimum='0' maximum='100' value='{model2.getRatio()}' - onStateChanged='model2.setRatio(_ratio.getValue())'/> + <JSlider id='_ratio' minimum='0' maximum='100' value='{model2.getRatio()}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> </cell> </row> </Table> @@ -131,8 +135,8 @@ </cell> <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> <JPanel border='{BorderFactory.createTitledBorder("Model2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> <row> <cell> <JLabel text='Text:'/> @@ -172,8 +176,8 @@ <JLabel text='FirstName:'/> </cell> <cell weightx='1'> - <JTextField id='firstName' text='{identity.getFirstName()}' - onKeyReleased='identity.setFirstName(firstName.getText())'/> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> </cell> </row> <row> @@ -181,8 +185,8 @@ <JLabel text='LastName:'/> </cell> <cell weightx='1'> - <JTextField id='lastName' text='{identity.getLastName()}' - onKeyReleased='identity.setLastName(lastName.getText())'/> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> </cell> </row> <row> @@ -190,8 +194,8 @@ <JLabel text='Email:'/> </cell> <cell weightx='1'> - <JTextField id='email2' text='{identity.getEmail()}' - onKeyReleased='identity.setEmail(email2.getText())'/> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> </cell> </row> @@ -200,8 +204,8 @@ <JLabel text='Age:'/> </cell> <cell> - <JSlider id='age' minimum='0' maximum='100' value='{identity.getAge()}' - onStateChanged='identity.setAge(age.getValue())'/> + <JSlider id='age' minimum='0' maximum='100' value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> </cell> </row> </Table> @@ -209,8 +213,8 @@ </cell> <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> <row> <cell> <JLabel text='FirstName:'/> @@ -227,8 +231,8 @@ <JLabel text='{identity.getLastName()}'/> </cell> </row> - <row> - <cell> + <row> + <cell> <JLabel text='Email:'/> </cell> <cell weightx='1'> @@ -250,7 +254,8 @@ </row> <row> <cell columns='2' fill="both"> - <JPanel border='{BorderFactory.createTitledBorder("Errors")}' layout='{new GridLayout()}' height='200' width='500'> + <JPanel border='{BorderFactory.createTitledBorder("Errors")}' layout='{new GridLayout()}' height='200' + width='500'> <JScrollPane> <JList model='{errors}'/> </JScrollPane> Modified: lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx 2008-11-30 22:23:22 UTC (rev 1041) +++ lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx 2008-12-01 02:50:26 UTC (rev 1042) @@ -7,7 +7,8 @@ <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors'/> <!-- validators --> - <BeanValidator id='validator3' autoField='true' beanClass='testcases.validator.ok.Identity' errorListModel='errors'> + <BeanValidator id='validator3' autoField='true' beanClass='testcases.validator.ok.Identity' errorListModel='errors' + scope='ERROR'> <field name="email" component="email2"/> </BeanValidator>