[Buix-commits] r1291 - in jaxx/trunk: jaxx-runtime-api jaxx-runtime-api/src/main/java/jaxx/runtime jaxx-runtime-validator jaxx-runtime-validator/src/main/java/jaxx/runtime jaxx-runtime-validator/src/main/java/jaxx/runtime/validator jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field jaxx-runtime-validator/src/main/resources jaxx-runtime-validator/src/main/resources/i18n jaxx-runtime-validator/src/test/java/jaxx/runtime/validator jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field
Author: tchemit Date: 2009-04-04 17:05:55 +0000 (Sat, 04 Apr 2009) New Revision: 1291 Added: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DataContext.java jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DecoratorUtils.java jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/ jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-en_GB.properties jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-fr_FR.properties jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidator.java jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/ jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-en_GB.properties jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-fr_FR.properties jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractValidatorBeanFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionBean.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ValidatorBean.java jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/FieldExpressionBean-error-validation.xml jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/ValidatorBean-error-validation.xml Removed: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/ValidatorBean.java jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-error-validation.xml Modified: jaxx/trunk/jaxx-runtime-api/changelog.txt jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/Decorator.java jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DefaultJAXXContext.java jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/JXPathDecorator.java jaxx/trunk/jaxx-runtime-validator-swing/pom.xml jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/SwingValidatorUtil.java jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java jaxx/trunk/jaxx-runtime-validator/changelog.txt jaxx/trunk/jaxx-runtime-validator/pom.xml jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/BeanValidatorUtil.java jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionUniqueKeyValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingDirectoryFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingFileFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingDirectoryFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingFileFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/RequiredFileFieldValidatorTest.java jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties jaxx/trunk/jaxx-runtime-validator/src/test/resources/validators.xml Log: little works :) see in changelog ... Modified: jaxx/trunk/jaxx-runtime-api/changelog.txt =================================================================== --- jaxx/trunk/jaxx-runtime-api/changelog.txt 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-api/changelog.txt 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,4 +1,6 @@ 1.3 chemit 20090320 + * 20090404 [chemit] - introduce DataContext class + * 20090331 [chemit] - introduce DecoratorUtils class * 20090302 [chemit] - add pcs in ApplicationContext - add method in Util to filter JAXX property changed listeners Added: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DataContext.java =================================================================== --- jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DataContext.java (rev 0) +++ jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DataContext.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,355 @@ +package jaxx.runtime; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Un contexte de données qui permet l'utilisation des bindings sur les + * entrées du contexte. + * + * TODO javadoc + * + * @author tony + * @since 1.3 + */ +public abstract class DataContext { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(DataContext.class); + /** le context qui contient les données */ + protected final DefaultJAXXContext delegate; + /** la definition de l'entree actuallement selectionnee */ + protected DataContextEntry<?> currentEntry; + /** to manage properties modifications */ + protected final PropertyChangeSupport pcs; + protected DataContextEntry<?>[] entries; + protected final String[] DEFAULT_JAXX_PCS; + + public abstract String getContextPath(Object e); + + public DataContext(String[] DEFAULT_JAXX_PCS, DataContextEntry<?>[] entries) { + this.DEFAULT_JAXX_PCS = DEFAULT_JAXX_PCS; + this.entries = entries; + delegate = new DefaultJAXXContext() { + + @Override + protected void setUi(JAXXObject ui) { + throw new IllegalStateException("can not use this method for this type of context"); + } + + @Override + public <O extends Container> O getParentContainer(Class<O> clazz) { + throw new IllegalStateException("can not use this method for this type of context"); + } + + @Override + public <O extends Container> O getParentContainer(Object top, Class<O> clazz) { + throw new IllegalStateException("can not use this method for this type of context"); + } + + @Override + protected JAXXObject getUi() { + throw new IllegalStateException("can not use this method for this type of context"); + } + + @Override + protected void setParentContext(JAXXContext parentContext) { + throw new IllegalStateException("can not use this method for this type of context"); + } + + @Override + protected JAXXContext getParentContext() { + return null; + } + }; + pcs = new PropertyChangeSupport(this); + } + + public DefaultJAXXContext getDelegate() { + return delegate; + } + + public Iterable<? extends DataContextEntry<?>> iterateOnAll() { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> iterateToLevel(final int level) { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, level); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> reverseIterateOnAll() { + + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, true); + } + }; + } + + public DataContextEntry<?> getCurrentEntry() { + return currentEntry; + } + + public DataContextEntry<?> getEntry(String path) { + for (DataContextEntry<?> scope : reverseIterateOnAll()) { + if (scope.acceptPath(path)) { + return scope; + } + } + return null; + } + + public DataContextEntry<?> getEntry(Class<?> type) { + for (DataContextEntry<?> scope : iterateOnAll()) { + if (scope.acceptType(type)) { + return scope; + } + } + return null; + } + + public void updateSelectedData(String path, Object data, UpdateDataContext updator) { + + if (currentEntry != null) { + + if (log.isDebugEnabled()) { + log.debug("remove from old entry " + currentEntry); + } + for (DataContextEntry<?> s : currentEntry) { + if (log.isTraceEnabled()) { + log.trace("remove entry " + s); + } + updator.onRemovingData(delegate, s); + } + } + + currentEntry = getEntry(path); + + if (log.isDebugEnabled()) { + log.debug("new entry " + currentEntry + " for path " + path); + } + + if (currentEntry != null) { + + for (DataContextEntry<?> s : iterateToLevel(currentEntry.getLevel())) { + + updator.onAddingData(delegate, s, path); + } + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void removeJaxxPropertyChangeListener() { + PropertyChangeListener[] toRemove = Util.findJaxxPropertyChangeListener(DEFAULT_JAXX_PCS, getPropertyChangeListeners()); + if (toRemove == null || toRemove.length == 0) { + return; + } + if (log.isDebugEnabled()) { + log.debug("before remove : " + getPropertyChangeListeners().length); + log.debug("toRemove : " + toRemove.length); + } + for (PropertyChangeListener listener : toRemove) { + removePropertyChangeListener(listener); + } + if (log.isDebugEnabled()) { + log.debug("after remove : " + getPropertyChangeListeners().length); + } + } + + protected void firePropertyChange(String name, Object oldValue, Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } + + public void close() throws Exception { + delegate.clear(); + } + + public void clear() { + delegate.clear(); + } + + public static abstract class DataContextEntry<E> implements Iterable<DataContextEntry<?>> { + + private final int level; + private final DataContextEntry<?> previous; + private final DataContextEntry[] parents; + private Class<E> klass; + + public DataContextEntry(Class<E> klass, DataContextEntry<?> previous) { + this.previous = previous; + this.level = previous.level + 1; + this.klass = klass; + this.parents = new DataContextEntry[level]; + int i = level; + while (i > 0) { + parents[--i] = previous; + previous = previous.previous; + } + } + + public DataContextEntry(Class<E> klass) { + this.level = 0; + this.klass = klass; + this.previous = null; + this.parents = new DataContextEntry[0]; + } + + public Class<E> getKlass() { + return klass; + } + + public int getLevel() { + return level; + } + + public DataContextEntry[] getParents() { + return parents; + } + + public abstract Pattern getPattern(); + + public abstract String getContextPath(Object... args); + + public E getData(JAXXContext c) { + return c.getContextValue(klass, null); + } + + public E getData(JAXXContext c, String context) { + return c.getContextValue(klass, context); + } + + public boolean acceptPath(String path) { + return getPattern().matcher(path).matches(); + } + + public boolean acceptType(Class<?> type) { + return klass.isAssignableFrom(type); + } + + @Override + public Iterator<DataContextEntry<?>> iterator() { + int length = parents.length; + DataContextEntry[] t = new DataContextEntry[length + 1]; + System.arraycopy(parents, 0, t, 0, length); + t[length] = this; + return new DataContextEntryIterator(t, true); + } + + @Override + public String toString() { + return super.toString() + "<type: " + klass.getSimpleName() + ">"; + } + } + + public static interface UpdateDataContext { + + void onRemovingData(JAXXContext context, DataContextEntry entry); + + void onAddingData(JAXXContext context, DataContextEntry entry, String path); + } + + public static class DataContextEntryIterator implements Iterator<DataContextEntry<?>> { + + protected final DataContextEntry[] datas; + protected final boolean reverse; + protected final int level; + protected int index; + + public DataContextEntryIterator(DataContextEntry[] datas) { + this(datas, false, -1); + } + + public DataContextEntryIterator(DataContextEntry[] datas, int level) { + this(datas, false, level); + } + + public DataContextEntryIterator(DataContextEntry[] datas, boolean reverse) { + this(datas, reverse, -1); + } + + DataContextEntryIterator(DataContextEntry[] datas, boolean reverse, int level) { + this.datas = datas; + this.reverse = reverse; + if (reverse) { + index = datas.length; + } else { + index = -1; + } + this.level = level; + } + + @Override + public boolean hasNext() { + if (reverse) { + return index > 0; + } else { + return index + 1 < datas.length && (level == -1 || datas[index + 1].getLevel() <= level); + } + } + + @Override + public DataContextEntry<?> next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + if (reverse) { + index--; + } else { + index++; + } + return datas[index]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} Modified: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/Decorator.java =================================================================== --- jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/Decorator.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/Decorator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,6 +3,7 @@ /** * A simple contract to define a String decorator on any java objet. * + * @param <O> the type of decorated object * @author chemit */ public abstract class Decorator<O> implements java.io.Serializable { Added: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DecoratorUtils.java =================================================================== --- jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DecoratorUtils.java (rev 0) +++ jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DecoratorUtils.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,111 @@ +package jaxx.runtime; + +import java.util.List; + +/** + * + * Some usefull methods on {@link Decorator} to store and obtain decorators. + * + * Use the method {@link #registerDecorator(String, Decorator)} to register a new + * decorator. + * + * Use the method {@link #getDecorator(String)} to obtain a registred + * decorator based on his registred name. + * + * Use the method {@link #getDecorator(Class, tring)} to obtain a registred + * decorator based on the type of decorator and the registred name. + * + * @author tony + * @since 1.3 + */ +public class DecoratorUtils { + + protected static List<DecoratorContext<?>> cache; + + public static <T> void registerDecorator(String context, Decorator<T> decorator) { + DecoratorContext<T> result = getDecoratorContext(decorator.getInternalClass(), context); + + if (result != null) { + throw new IllegalArgumentException("there is an already register decorator " + result); + } + + if (cache == null) { + cache = new java.util.ArrayList<DecoratorContext<?>>(); + } + cache.add(new DecoratorContext<T>(context, decorator)); + } + + public static <T> Decorator<T> getDecorator(String context) { + Decorator<T> result = getDecorator(null, context); + return result; + } + + public static <T> Decorator<T> getDecorator(Class<T> type, String context) { + DecoratorContext<T> decoratorContext = getDecoratorContext(type, context); + Decorator<T> result = decoratorContext == null ? null : decoratorContext.getDecorator(); + return result; + } + + public static void clear() { + if (cache != null) { + cache.clear(); + } + } + + @SuppressWarnings({"unchecked"}) + protected static <T> DecoratorContext<T> getDecoratorContext(Class<T> type, String context) { + DecoratorContext<T> result = null; + if (cache != null) { + for (DecoratorContext<?> d : cache) { + if (type == null) { + if (d.accept(context)) { + result = (DecoratorContext<T>) d; + break; + } + continue; + } + if (d.accept(type, context)) { + result = (DecoratorContext<T>) d; + break; + } + } + } + return result; + } + + public static class DecoratorContext<T> { + + final String context; + final Decorator<T> decorator; + + public DecoratorContext(String context, Decorator<T> decorator) { + this.context = context; + this.decorator = decorator; + } + + public String getContext() { + return context; + } + + public Decorator<T> getDecorator() { + return decorator; + } + + public Class<T> getType() { + return decorator.getInternalClass(); + } + + public boolean accept(Class<?> type, String context) { + return getType().isAssignableFrom(type) && accept(context); + } + + public boolean accept(String context) { + return ((this.context == null && context == null) || (this.context != null && this.context.equals(context))); + } + + @Override + public String toString() { + return super.toString() + "<type: " + getType().getName() + ", context :" + context + ">"; + } + } +} Modified: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DefaultJAXXContext.java =================================================================== --- jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DefaultJAXXContext.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/DefaultJAXXContext.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -6,6 +6,7 @@ import java.awt.Container; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -23,16 +24,12 @@ public class DefaultJAXXContext implements JAXXContext { protected static final JAXXContextEntryDef<JAXXContext> PARENT_CONTEXT_ENTRY = newDef(JAXXContext.class); - /** to use log facility, just put in your code: log.info(\"...\"); */ static private final Log log = LogFactory.getLog(DefaultJAXXContext.class); - /** l'ui auquel est rattache le context */ protected JAXXObject ui; - /** le context parent */ protected JAXXContext parentContext; - /** les données contenues dans le context */ protected final Map<JAXXContextEntryDef, Object> data; @@ -45,10 +42,12 @@ this.ui = ui; } + @Override public <T> void setContextValue(T o) { setContextValue(o, null); } + @Override public <T> void setContextValue(T o, String name) { if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { setParentContext((JAXXContext) o); @@ -66,11 +65,13 @@ data.put(entry, o); } + @Override public <T> T getContextValue(Class<T> clazz) { return getContextValue(clazz, null); } @SuppressWarnings({"unchecked"}) + @Override public <T> T getContextValue(Class<T> clazz, String name) { if (PARENT_CONTEXT_ENTRY.accept(clazz, name)) { return (T) getParentContext(); @@ -87,28 +88,32 @@ return null; } - JAXXContext parentContext = getParentContext(); - if (parentContext == null) { + JAXXContext parent = getParentContext(); + if (parent == null) { // no parent context, so no value find return null; } // seek in parent context - return parentContext.getContextValue(clazz, name); + return parent.getContextValue(clazz, name); } + @Override public <T> void removeContextValue(Class<T> klazz) { removeContextValue(klazz, null); } + @Override public <T> void removeContextValue(Class<T> klazz, String name) { remove0(klazz, name); } + @Override public <O extends Container> O getParentContainer(Class<O> clazz) { return this.getParentContainer(ui, clazz); } @SuppressWarnings({"unchecked"}) + @Override public <O extends Container> O getParentContainer(Object top, Class<O> clazz) { if (ui == null) { throw new IllegalStateException("no ui attached to this context"); @@ -126,6 +131,28 @@ return (O) parent; } + /** + * Obtain all the keys of data for a given type. + * + * @param klass the type of searched keys + * @return the array of all names of keys for the given type of data + * @since 1.3 + */ + public String[] getKeys(Class<?> klass) { + List<String> keys = new java.util.ArrayList<String>(); + for (JAXXContextEntryDef key : data.keySet()) { + if (key.getKlass() == klass) { + keys.add(key.getName()); + } + } + return keys.toArray(new String[keys.size()]); + + } + + public void clear() { + data.clear(); + } + protected JAXXObject getUi() { return ui; } @@ -160,14 +187,14 @@ return null; } // try in parentContext - JAXXContext parentContext = getParentContext(); + JAXXContext parent = getParentContext(); - if (parentContext == null) { + if (parent == null) { return null; } - if (parentContext instanceof DefaultJAXXContext) { - return ((DefaultJAXXContext) parentContext).remove0(klazz, name); + if (parent instanceof DefaultJAXXContext) { + return ((DefaultJAXXContext) parent).remove0(klazz, name); } return null; Modified: jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/JXPathDecorator.java =================================================================== --- jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/JXPathDecorator.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-api/src/main/java/jaxx/runtime/JXPathDecorator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -35,7 +35,6 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ private static final Log log = LogFactory.getLog(JXPathDecorator.class); - private static final long serialVersionUID = 1L; /** @@ -83,7 +82,6 @@ public static class JXPathComparator<O> implements Comparator<O> { protected Map<O, Comparable<Comparable>> valueCache; - private final String expression; public JXPathComparator(String expression) { @@ -119,12 +117,9 @@ * using using the jxpath tokens. */ protected String expression; - /** list of jxpath tokens to apply on expression */ protected String[] tokens; - protected transient Comparator<O> comparator; - private static final long serialVersionUID = 1L; public Context(String expression, String[] tokens) { @@ -152,25 +147,30 @@ return "<expression:" + expression + ", tokens:" + Arrays.toString(tokens) + ">"; } } - /** the computed context of the decorator */ protected Context<O> context; - /** nb jxpath tokens to compute */ protected int nbToken; - /** the initial expression used to compute the decorator context. */ protected String initialExpression; + @Override public String toString(Object bean) { if (bean == null) { return null; } JXPathContext jxcontext = JXPathContext.newContext(bean); Object[] args = new Object[nbToken]; + for (int i = 0; i < nbToken; i++) { - args[i] = getTokenValue(jxcontext, context.tokens[i]); + try { + args[i] = getTokenValue(jxcontext, context.tokens[i]); + } catch (Exception e) { + log.error("can not obtain token " + context.tokens[i] + "on object " + bean + " for reason " + e.getMessage(), e); + + } } + return String.format(context.expression, args); } Modified: jaxx/trunk/jaxx-runtime-validator/changelog.txt =================================================================== --- jaxx/trunk/jaxx-runtime-validator/changelog.txt 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/changelog.txt 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,4 +1,9 @@ 1.3 chemit 20090321 + * 20090404 [chemit] - can now use a shared instance of ValueStack (in BeanValidatorUtil) + * 20090401 [chemit] - introduce a extended fieldexpression validator where we can push extra parameters + - improve tests + - add useSensitiveContext in CollectionFieldExpressionValidator. + * 20090320 [chemit] - rename and move ValidationUtil to jaxx.runtime.BeanValidatorUtil * 20090319 [chemit] - refactor Validator : now can deal with scopes, improve design Modified: jaxx/trunk/jaxx-runtime-validator/pom.xml =================================================================== --- jaxx/trunk/jaxx-runtime-validator/pom.xml 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/pom.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -47,6 +47,23 @@ <!-- ************************************************************* --> <packaging>jar</packaging> + <build> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <version>${i18n.version}</version> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> <!-- ************************************************************* --> <!-- *** Build Environment ************************************** --> <!-- ************************************************************* --> Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/BeanValidatorUtil.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/BeanValidatorUtil.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/BeanValidatorUtil.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,5 +1,9 @@ package jaxx.runtime; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.ValueStackFactory; import jaxx.runtime.validator.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -22,7 +26,27 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private final Log log = LogFactory.getLog(BeanValidatorUtil.class); + /** + * a shared value stack to allow external operations on it (for example + * add some datas in stack to be usedby validators + */ + static private ValueStack sharedValueStack; + public static synchronized ValueStack getSharedValueStack() { + if (sharedValueStack == null) { + + // init context + ConfigurationManager confManager = new ConfigurationManager(); + Configuration conf = confManager.getConfiguration(); + + sharedValueStack = conf.getContainer().getInstance(ValueStackFactory.class).createValueStack(); + if (log.isDebugEnabled()) { + log.debug("init shared value stack " + sharedValueStack); + } + } + return sharedValueStack; + } + protected BeanValidatorUtil() { // no instance } @@ -148,5 +172,4 @@ throw new IllegalStateException("could not acquire PropertyChangeListener bean info for " + beanClass + " for reason " + ex.getMessage(), ex); } } - } Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -107,7 +107,7 @@ } public Set<BeanValidatorScope> getScopes() { - return new java.util.HashSet< BeanValidatorScope>(validators.keySet()); + return new java.util.HashSet<BeanValidatorScope>(validators.keySet()); } /** @@ -342,6 +342,9 @@ errors.add(conversionError); } else { errors = java.util.Collections.singletonList(conversionError); + if (newMessages == XWorkBeanValidator.EMPTY_RESULT) { + newMessages = new java.util.HashMap<String, List<String>>(); + } // add the concrete conversion error newMessages.put(entry.getKey(), errors); } Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,5 +1,7 @@ package jaxx.runtime.validator; +import static org.codelutin.i18n.I18n.n_; + /** * The differents levels of messages in validation process. * <p/> @@ -10,25 +12,35 @@ * @author chemit */ public enum BeanValidatorScope { + /** * the error scope level. * * When a message of a such scope is found on a validator, then the validator * is invalid and modified. */ - ERROR, + ERROR(n_("validator.scope.error.label")), /** * the warning scope level. * * When a message of a such scope is found on a validator, then the validator * is still valid but modified. */ - WARNING, + WARNING(n_("validator.scope.warning.label")), /** * the information scope level. * * When a message of a sucg scope is found on a validator, then the * validator is still valid and not modified. */ - INFO + INFO(n_("validator.scope.info.label")); + private final String label; + + private BeanValidatorScope(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } } Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import jaxx.runtime.BeanValidatorUtil; /** * @@ -37,7 +38,7 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ private static final Log log = LogFactory.getLog(XWorkBeanValidator.class); - private final static Map<String, List<String>> EMPTY_RESULT = Collections.unmodifiableMap(new HashMap<String, List<String>>()); + protected final static Map<String, List<String>> EMPTY_RESULT = Collections.unmodifiableMap(new HashMap<String, List<String>>()); /** the type of bean to validate */ protected final Class<B> beanClass; /** the validation named context (can be null) */ @@ -55,26 +56,43 @@ protected ActionContext context; public XWorkBeanValidator(Class<B> beanClass, String contextName) { - this(beanClass, contextName, true); + this(beanClass, contextName, true, BeanValidatorUtil.getSharedValueStack()); } + public XWorkBeanValidator(Class<B> beanClass, String contextName, ValueStack vs) { + this(beanClass, contextName, true, vs); + } + public XWorkBeanValidator(Class<B> beanClass, String contextName, boolean includeDefaultContext) { + this(beanClass, contextName, includeDefaultContext, BeanValidatorUtil.getSharedValueStack()); + } + public XWorkBeanValidator(Class<B> beanClass, String contextName, boolean includeDefaultContext, ValueStack vs) { + this.beanClass = beanClass; this.includeDefaultContext = includeDefaultContext; validationSupport = new ValidationAwareSupport(); validationContext = new DelegatingValidatorContext(validationSupport); - // init context - ConfigurationManager confManager = new ConfigurationManager(); - Configuration conf = confManager.getConfiguration(); + if (vs == null) { + // create a standalone value stack + ConfigurationManager confManager = new ConfigurationManager(); + Configuration conf = confManager.getConfiguration(); + vs = conf.getContainer().getInstance(ValueStackFactory.class).createValueStack(); + if (log.isDebugEnabled()) { + log.info("create a standalone value stack " + vs); + } + } else { + if (log.isDebugEnabled()) { + log.debug("use given value stack " + vs); + } + } - ValueStack vs = conf.getContainer().getInstance(ValueStackFactory.class).createValueStack(); context = new ActionContext(vs.getContext()); ActionContext.setContext(context); // init validator - validator = conf.getContainer().getInstance(ActionValidatorManager.class, "no-annotations"); + validator = context.getContainer().getInstance(ActionValidatorManager.class, "no-annotations"); // init context setContextName(contextName); Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -25,6 +25,30 @@ } /** le mode de validation sur la liste */ protected Mode mode; + /** + * drapeau pour utiliser le contexte de parcours pour valider + * l'expression, on dispose donc alors des variables previous, current, + * index, size et empty dans l'expression. + * + * Sinon l'expression s'applique directement sur l'entrée courant dans le + * parcours sans préfixe. + */ + protected boolean useSensitiveContext; + /** + * expression a valider sur la premiètre entrée de la collection. + * + * Note : Pour le moment, on autorise uniquement cela en mode ALL. + */ + protected String expressionForFirst; + /** + * expression a valider sur la dernière entrée de la collection. + * + * Note : Pour le moment, on autorise uniquement cela en mode ALL. + */ + protected String expressionForLast; + /** le context de parcours */ + protected WalkerContext c; + private boolean useFirst, useLast; public Mode getMode() { return mode; @@ -34,16 +58,53 @@ this.mode = mode; } + public boolean isUseSensitiveContext() { + return useSensitiveContext; + } + + public void setUseSensitiveContext(boolean useSensitiveContext) { + this.useSensitiveContext = useSensitiveContext; + } + + public String getExpressionForFirst() { + return expressionForFirst; + } + + public void setExpressionForFirst(String expressionForFirst) { + this.expressionForFirst = expressionForFirst; + } + + public String getExpressionForLast() { + return expressionForLast; + } + + public void setExpressionForLast(String expressionForLast) { + this.expressionForLast = expressionForLast; + } + @Override public void validate(Object object) throws ValidationException { if (mode == null) { - throw new ValidationException("no mode defined"); + throw new ValidationException("no mode defined!"); } + useFirst = expressionForFirst != null && !expressionForFirst.trim().isEmpty(); + useLast = expressionForLast != null && !expressionForLast.trim().isEmpty(); + if (useFirst && mode != Mode.ALL) { + throw new ValidationException("can only use expressionForFirst in mode ALL but was " + mode); + } + if (useLast && mode != Mode.ALL) { + throw new ValidationException("can only use expressionForLast in mode ALL but was " + mode); + } + String fieldName = getFieldName(); Collection<?> col = getCollection(object); + if (useSensitiveContext) { + c = new WalkerContext(col.size()); + } + boolean answer; switch (mode) { @@ -129,10 +190,36 @@ } protected boolean validateOneEntry(Object object) throws ValidationException { - // obtain the validation of one entry of the collection + + Boolean answer = Boolean.FALSE; + + boolean extraExpression = false; + + if (useSensitiveContext) { + c.addCurrent(object); + object = c; + + if (c.isFirst() && useFirst) { + // on valide l'expression sur la premiètre entrée + answer = evaluateExpression(expressionForFirst, object); + extraExpression = true; + } + if (c.isLast() && useLast) { + // on valide l'expression sur la dernière entrée + answer = (!extraExpression || answer) && evaluateExpression(expressionForLast, object); + extraExpression = true; + } + } + + answer = (!extraExpression || answer) && evaluateExpression(getExpression(), object); + + return answer; + } + + protected boolean evaluateExpression(String expression, Object object) throws ValidationException { Object obj = null; try { - obj = getFieldValue(getExpression(), object); + obj = getFieldValue(expression, object); } catch (ValidationException e) { throw e; } catch (Exception e) { @@ -144,7 +231,7 @@ if (obj != null && obj instanceof Boolean) { answer = (Boolean) obj; } else { - log.warn("Got result of " + obj + " when trying to get Boolean."); + log.warn("Got result of " + obj + " when trying to get Boolean for expression " + expression); } return answer; } @@ -183,4 +270,50 @@ public String getValidatorType() { return "collectionFieldExpression"; } + + public class WalkerContext { + + protected final int size; + + public WalkerContext(int size) { + this.size = size; + } + protected int index = -1; + protected Object current; + protected Object previous; + + public void addCurrent(Object current) { + index++; + previous = this.current; + this.current = current; + } + + public Object getCurrent() { + return current; + } + + public int getIndex() { + return index; + } + + public Object getPrevious() { + return previous; + } + + public int getSize() { + return size; + } + + public boolean isEmpty() { + return size == 0; + } + + public boolean isFirst() { + return index == 0; + } + + public boolean isLast() { + return index == size - 1; + } + } } Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidator.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidator.java (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidator.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,175 @@ +package jaxx.runtime.validator.field; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.codelutin.util.ConverterUtil; + +/** + * Extends {@link FieldExpressionValidator} to add some extra parameters available + * in the {@link #getExpression()} + * + * @author tony + * @since 1.3 + */ +public class FieldExpressionWithParamsValidator extends FieldExpressionValidator { + + protected static final Pattern EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(false|true)"); + protected static final Pattern EXTRA_SHORT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + protected static final Pattern EXTRA_INT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + protected static final Pattern EXTRA_LONG_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+)"); + protected static final Pattern EXTRA_DOUBLE_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(\\d+\\.\\d+)"); + protected static final Pattern EXTRA_STRING_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(.+)"); + protected ValueStack stack; + protected String booleanParams; + protected String shortParams; + protected String intParams; + protected String longParams; + protected String doubleParams; + protected String stringParams; + protected Map<String, Boolean> booleans; + protected Map<String, Short> shorts; + protected Map<String, Integer> ints; + protected Map<String, Long> longs; + protected Map<String, Double> doubles; + protected Map<String, String> strings; + + public String getBooleanParams() { + return booleanParams; + } + + public void setBooleanParams(String booleanParams) { + this.booleanParams = booleanParams; + } + + public String getDoubleParams() { + return doubleParams; + } + + public void setDoubleParams(String doubleParams) { + this.doubleParams = doubleParams; + } + + public String getIntParams() { + return intParams; + } + + public void setIntParams(String intParams) { + this.intParams = intParams; + } + + public String getLongParams() { + return longParams; + } + + public void setLongParams(String longParams) { + this.longParams = longParams; + } + + public String getShortParams() { + return shortParams; + } + + public void setShortParams(String shortParams) { + this.shortParams = shortParams; + } + + public String getStringParams() { + return stringParams; + } + + public void setStringParams(String stringParams) { + this.stringParams = stringParams; + } + + public Map<String, Boolean> getBooleans() { + return booleans; + } + + public Map<String, Double> getDoubles() { + return doubles; + } + + public Map<String, Integer> getInts() { + return ints; + } + + public Map<String, Long> getLongs() { + return longs; + } + + public Map<String, Short> getShorts() { + return shorts; + } + + public Map<String, String> getStrings() { + return strings; + } + + @Override + public String getValidatorType() { + return "fieldexpressionwithparams"; + } + + @Override + public void setValueStack(ValueStack stack) { + super.setValueStack(stack); + this.stack = stack; + } + + @Override + public void validate(Object object) throws ValidationException { + + booleans = initParams(Boolean.class, booleanParams, EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN); + shorts = initParams(Short.class, shortParams, EXTRA_SHORT_PARAM_ENTRY_PATTERN); + ints = initParams(Integer.class, intParams, EXTRA_INT_PARAM_ENTRY_PATTERN); + longs = initParams(Long.class, longParams, EXTRA_LONG_PARAM_ENTRY_PATTERN); + doubles = initParams(Double.class, doubleParams, EXTRA_DOUBLE_PARAM_ENTRY_PATTERN); + strings = initParams(String.class, stringParams, EXTRA_STRING_PARAM_ENTRY_PATTERN); + + boolean pop = false; + if (!stack.getRoot().contains(this)) { + stack.push(this); + pop = true; + } + + try { + super.validate(object); + } finally { + if (pop) { + stack.pop(); + } + } + + } + + protected <T> Map<String, T> initParams(Class<T> klass, String extraParams, Pattern pattern) throws ValidationException { + + if (extraParams == null || extraParams.isEmpty()) { + // not using + return null; + } + + StringTokenizer stk = new StringTokenizer(extraParams, "|"); + Map<String, T> result = new java.util.TreeMap<String, T>(); + while (stk.hasMoreTokens()) { + String entry = stk.nextToken(); + Matcher matcher = pattern.matcher(entry); + if (!matcher.matches()) { + throw new ValidationException("could not parse for extra params " + extraParams + " for type " + klass.getName()); + } + String paramName = matcher.group(1); + String paramValueStr = matcher.group(2); + T paramValue = ConverterUtil.convert(klass, paramValueStr); + if (log.isDebugEnabled()) { + log.debug("detected extra param : <type:" + klass + ", name:" + paramName + ", value:" + paramValue + ">"); + } + result.put(paramName, paramValue); + } + return result; + } +} Added: jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-en_GB.properties =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-en_GB.properties (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-en_GB.properties 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,3 @@ +validator.scope.error.label=Error +validator.scope.info.label=Information +validator.scope.warning.label=Warning Added: jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-fr_FR.properties =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-fr_FR.properties (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/main/resources/i18n/jaxx-runtime-validator-fr_FR.properties 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,3 @@ +validator.scope.error.label=Erreur +validator.scope.info.label=Information +validator.scope.warning.label=Avertissement Deleted: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/ValidatorBean.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/ValidatorBean.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/ValidatorBean.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,158 +0,0 @@ -package jaxx.runtime.validator; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.io.File; -import java.util.Collection; - -public class ValidatorBean { - - public static class ValidatorBeanEntry { - - protected int intValue; - protected String stringValue; - protected String stringValue2; - - public ValidatorBeanEntry(int intValue, String stringValue) { - this.intValue = intValue; - this.stringValue = stringValue; - } - - public ValidatorBeanEntry(int intValue, String stringValue, String stringValue2) { - this.intValue = intValue; - this.stringValue = stringValue; - this.stringValue2 = stringValue2; - } - - public int getIntValue() { - return intValue; - } - - public void setIntValue(int intValue) { - this.intValue = intValue; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public String getStringValue2() { - return stringValue2; - } - - public void setStringValue2(String stringValue2) { - this.stringValue2 = stringValue2; - } - } - - protected File existingFile; - protected File notExistingFile; - - protected File existingDirectory; - protected File notExistingDirectory; - - protected Collection<ValidatorBeanEntry> entries; - - protected String stringValue; - - protected ValidatorBeanEntry entry; - - PropertyChangeSupport p; - - public ValidatorBean() { - p = new PropertyChangeSupport(this); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - p.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - p.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - p.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - p.removePropertyChangeListener(propertyName, listener); - } - - public String getStringValue() { - return stringValue; - } - - public File getExistingFile() { - return existingFile; - } - - public File getNotExistingFile() { - return notExistingFile; - } - - public File getExistingDirectory() { - return existingDirectory; - } - - public File getNotExistingDirectory() { - return notExistingDirectory; - } - - public ValidatorBeanEntry getEntry() { - return entry; - } - - public Collection<ValidatorBeanEntry> getEntries() { - return entries; - } - - public void setStringValue(String stringValue) { - String old = this.stringValue; - this.stringValue = stringValue; - p.firePropertyChange("stringValue", old, existingFile); - } - - public void setExistingFile(File existingFile) { - File old = this.existingFile; - this.existingFile = existingFile; - p.firePropertyChange("existingFile", old, existingFile); - } - - public void setNotExistingFile(File notExistingFile) { - File old = this.notExistingFile; - this.notExistingFile = notExistingFile; - p.firePropertyChange("notExistingFile", old, notExistingFile); - } - - public void setExistingDirectory(File existingDirectory) { - File old = this.existingDirectory; - this.existingDirectory = existingDirectory; - p.firePropertyChange("existingDirectory", old, existingDirectory); - } - - public void setNotExistingDirectory(File notExistingDirectory) { - File old = this.notExistingDirectory; - this.notExistingDirectory = notExistingDirectory; - p.firePropertyChange("notExistingDirectory", old, notExistingDirectory); - } - - public void setEntries(Collection<ValidatorBeanEntry> entries) { - this.entries = entries; - // set null oldValue to always fire event - // otherwise it could been not sent... - p.firePropertyChange("entries", null, entries); - } - - public void setEntry(ValidatorBeanEntry entry) { - this.entry = entry; - p.firePropertyChange("entry", null, entry); - } - - - -} \ No newline at end of file Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,10 +3,10 @@ import java.io.File; import jaxx.runtime.validator.BeanValidator; import jaxx.runtime.validator.BeanValidatorField; -import jaxx.runtime.validator.ValidatorBean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -17,34 +17,59 @@ * To implements a test on a new validator, just extends this class * and implements the method {@link #testValidator()}. * + * @param <B> the type of bean to validate. + * * @author chemit */ -public abstract class AbstractFieldValidatorTest extends Assert { +public abstract class AbstractFieldValidatorTest<B> extends Assert { /** to use log facility, just put in your code: log.info(\"...\"); */ static private final Log log = LogFactory.getLog(AbstractFieldValidatorTest.class); - static protected BeanValidator<ValidatorBean> validator; - static protected File basedir; - protected ValidatorBean bean; + protected static BeanValidator cacheValidator; + protected static File basedir; + protected final Class<B> type; + protected BeanValidator<B> validator; + protected B bean; + public AbstractFieldValidatorTest(Class<B> type) { + this.type = type; + } + /** - * the moethod to implements testing the given validator on the given bean. + * the method to test the given validator on the given bean. * + * When coming here a validator and bean were instanciated and the bean was + * setted into validator via setBean method. + * * @throws Exception if any error ? */ public abstract void testValidator() throws Exception; @Before + @SuppressWarnings("unchecked") public void setUp() throws Exception { log.debug("start test " + getClass().getSimpleName()); - validator.setBean(bean = new ValidatorBean()); + bean = type.newInstance(); + if (cacheValidator == null) { + validator = validator = new BeanValidator<B>(type, null); + cacheValidator = validator; + } else { + validator = cacheValidator; + } + validator.setBean(bean); } @After + @SuppressWarnings("unchecked") public void tearDown() { validator.setBean(null); } + @AfterClass + public static void afterclass() throws Exception { + cacheValidator = null; + } + @BeforeClass public static void initValidator() throws Exception { @@ -53,20 +78,20 @@ b = new File("").getAbsolutePath(); } basedir = new File(b); - validator = new BeanValidator<ValidatorBean>(ValidatorBean.class, null); } + @SuppressWarnings("unchecked") protected void assertFieldInError(String fieldName, String error, boolean required) { - BeanValidatorField<ValidatorBean> field = validator.getField(fieldName); - if (field !=null && field.getErrors() != null) { + BeanValidatorField<B> field = validator.getField(fieldName); + if (field != null && field.getErrors() != null) { for (String o : field.getErrors()) { if (o.equals(error)) { - assertTrue(required); + assertTrue("error " + error + " should not exist but was found.", required); return; } } } // error was not found - assertFalse(required); + assertFalse("error " + error + " should exist but was not found.", required); } } \ No newline at end of file Added: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractValidatorBeanFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractValidatorBeanFieldValidatorTest.java (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractValidatorBeanFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,14 @@ +package jaxx.runtime.validator.field; + +/** + * Abstract class to test a specific validator for the {@link Validatorbean}. + * + * @author chemit + * @since 1.3 + */ +public abstract class AbstractValidatorBeanFieldValidatorTest extends AbstractFieldValidatorTest<ValidatorBean> { + + public AbstractValidatorBeanFieldValidatorTest() { + super(ValidatorBean.class); + } +} \ No newline at end of file Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,14 +1,18 @@ package jaxx.runtime.validator.field; -import jaxx.runtime.validator.ValidatorBean.ValidatorBeanEntry; +import jaxx.runtime.validator.field.ValidatorBean.ValidatorBeanEntry; import java.util.Arrays; /** @author chemit */ -public class CollectionFieldExpressionValidatorTest extends AbstractFieldValidatorTest { +public class CollectionFieldExpressionValidatorTest extends AbstractValidatorBeanFieldValidatorTest { - static protected ValidatorBeanEntry beanEntry = new ValidatorBeanEntry(0, "stringValue"); - static protected ValidatorBeanEntry beanEntry2 = new ValidatorBeanEntry(0, "fake"); + protected static final String PROPERTY = "entries"; + static protected ValidatorBeanEntry beanEntry0 = new ValidatorBeanEntry(0, "stringValue"); + static protected ValidatorBeanEntry beanEntry0Bis = new ValidatorBeanEntry(0, "fake"); + static protected ValidatorBeanEntry beanEntry1 = new ValidatorBeanEntry(1, "fake"); + static protected ValidatorBeanEntry beanEntry3 = new ValidatorBeanEntry(3, "fake"); + static protected ValidatorBeanEntry beanEntry5 = new ValidatorBeanEntry(5, "fake"); @org.junit.Test @Override @@ -16,41 +20,215 @@ assertNull(bean.getEntries()); // no entry - assertFieldInError("entries", "collectionFieldExpression.atLeastOne", true); - assertFieldInError("entries", "collectionFieldExpression.exactlyOne", true); - assertFieldInError("entries", "collectionFieldExpression.all", false); - assertFieldInError("entries", "collectionFieldExpression.none", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", false); + // add a matching etry - bean.setEntries(Arrays.asList(beanEntry)); + bean.setEntries(Arrays.asList(beanEntry0)); - assertFieldInError("entries", "collectionFieldExpression.atLeastOne", false); - assertFieldInError("entries", "collectionFieldExpression.exactlyOne", false); - assertFieldInError("entries", "collectionFieldExpression.all", false); - assertFieldInError("entries", "collectionFieldExpression.none", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); // two matching etries - bean.setEntries(Arrays.asList(beanEntry, beanEntry)); + bean.setEntries(Arrays.asList(beanEntry0, beanEntry0)); - assertFieldInError("entries", "collectionFieldExpression.atLeastOne", false); - assertFieldInError("entries", "collectionFieldExpression.exactlyOne", true); - assertFieldInError("entries", "collectionFieldExpression.all", false); - assertFieldInError("entries", "collectionFieldExpression.none", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); // add a none matching etry - bean.setEntries(Arrays.asList(beanEntry2)); + bean.setEntries(Arrays.asList(beanEntry0Bis)); - assertFieldInError("entries", "collectionFieldExpression.atLeastOne", true); - assertFieldInError("entries", "collectionFieldExpression.exactlyOne", true); - assertFieldInError("entries", "collectionFieldExpression.all", true); - assertFieldInError("entries", "collectionFieldExpression.none", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", false); // add a none matching etry and a matching entry - bean.setEntries(Arrays.asList(beanEntry2, beanEntry)); + bean.setEntries(Arrays.asList(beanEntry0Bis, beanEntry0)); - assertFieldInError("entries", "collectionFieldExpression.atLeastOne", false); - assertFieldInError("entries", "collectionFieldExpression.exactlyOne", false); - assertFieldInError("entries", "collectionFieldExpression.all", true); - assertFieldInError("entries", "collectionFieldExpression.none", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none", true); } + + @org.junit.Test + public void testValidatorWithContext() throws Exception { + assertNull(bean.getEntries()); + + // no entry + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a matching etry + bean.setEntries(Arrays.asList(beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a none matching etry + bean.setEntries(Arrays.asList(beanEntry0Bis)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + // add a none matching etry and a matching entry + bean.setEntries(Arrays.asList(beanEntry0Bis, beanEntry0)); + + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, "collectionFieldExpression.atLeastOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.all.useSensitiveContext", true); + assertFieldInError(PROPERTY, "collectionFieldExpression.exactlyOne.useSensitiveContext", false); + assertFieldInError(PROPERTY, "collectionFieldExpression.none.useSensitiveContext", false); + } + + @org.junit.Test + public void testValidatorWithContextAndFirst() throws Exception { + assertNull(bean.getEntries()); + String message = "collectionFieldExpression.all.useFirst"; + + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, false); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } + + @org.junit.Test + public void testValidatorWithContextAndLast() throws Exception { + assertNull(bean.getEntries()); + String message = "collectionFieldExpression.all.useLast"; + + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } + + @org.junit.Test + public void testValidatorWithContextAndFirstAndLast() throws Exception { + assertNull(bean.getEntries()); + + String message = "collectionFieldExpression.all.useFirstAndLast"; + // no entry + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + + bean.setEntries(Arrays.asList(beanEntry0Bis)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry1)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry0)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry1, beanEntry3)); + assertFieldInError(PROPERTY, message, true); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry1, beanEntry3, beanEntry5)); + assertFieldInError(PROPERTY, message, false); + + bean.setEntries(Arrays.asList(beanEntry0, beanEntry3, beanEntry1)); + assertFieldInError(PROPERTY, message, true); + } } Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionUniqueKeyValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionUniqueKeyValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/CollectionUniqueKeyValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,11 +1,11 @@ package jaxx.runtime.validator.field; -import jaxx.runtime.validator.ValidatorBean.ValidatorBeanEntry; +import jaxx.runtime.validator.field.ValidatorBean.ValidatorBeanEntry; import java.util.Arrays; /** @author chemit */ -public class CollectionUniqueKeyValidatorTest extends AbstractFieldValidatorTest { +public class CollectionUniqueKeyValidatorTest extends AbstractValidatorBeanFieldValidatorTest { static protected ValidatorBeanEntry beanEntry = new ValidatorBeanEntry(0, "stringValue"); static protected ValidatorBeanEntry beanEntry2 = new ValidatorBeanEntry(0, "fake"); Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingDirectoryFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingDirectoryFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingDirectoryFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,7 +3,7 @@ import java.io.File; /** @author chemit */ -public class ExistingDirectoryFieldValidatorTest extends AbstractFieldValidatorTest { +public class ExistingDirectoryFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { @org.junit.Test @Override Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingFileFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingFileFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ExistingFileFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,7 +3,7 @@ import java.io.File; /** @author chemit */ -public class ExistingFileFieldValidatorTest extends AbstractFieldValidatorTest { +public class ExistingFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { @org.junit.Test @Override Added: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionBean.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionBean.java (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionBean.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,103 @@ +package jaxx.runtime.validator.field; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * + * @author tony + */ +public class FieldExpressionBean { + + protected final PropertyChangeSupport p; + protected boolean booleanValue; + protected short shortValue; + protected int intValue; + protected long longValue; + protected double doubleValue; + protected String stringValue; + + public FieldExpressionBean() { + p = new PropertyChangeSupport(this); + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public double getDoubleValue() { + return doubleValue; + } + + public int getIntValue() { + return intValue; + } + + public long getLongValue() { + return longValue; + } + + public short getShortValue() { + return shortValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setBooleanValue(boolean newValue) { + Object oldValue = this.booleanValue; + this.booleanValue = newValue; + firePropertyChange("booleanValue", oldValue, newValue); + } + + public void setDoubleValue(double newValue) { + Object oldValue = this.doubleValue; + this.doubleValue = newValue; + firePropertyChange("doubleValue", oldValue, newValue); + } + + public void setIntValue(int newValue) { + Object oldValue = this.stringValue; + this.intValue = newValue; + firePropertyChange("intValue", oldValue, newValue); + } + + public void setLongValue(long newValue) { + Object oldValue = this.longValue; + this.longValue = newValue; + firePropertyChange("longValue", oldValue, newValue); + } + + public void setShortValue(short newValue) { + Object oldValue = this.shortValue; + this.shortValue = newValue; + firePropertyChange("shortValue", oldValue, newValue); + } + + public void setStringValue(String newValue) { + Object oldValue = this.stringValue; + this.stringValue = newValue; + firePropertyChange("stringValue", oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + p.firePropertyChange(propertyName, oldValue, newValue); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } +} Added: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidatorTest.java (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/FieldExpressionWithParamsValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,116 @@ +package jaxx.runtime.validator.field; + +/** @author chemit */ +public class FieldExpressionWithParamsValidatorTest extends AbstractFieldValidatorTest<FieldExpressionBean> { + + public static final String MESSAGE = "expression.too.big##100"; + public static final String MESSAGE2 = "expression.too.big##100##2000"; + + public FieldExpressionWithParamsValidatorTest() { + super(FieldExpressionBean.class); + } + + @org.junit.Test + @Override + public void testValidator() throws Exception { + + testBooleanType(); + testShortType(); + testIntType(); + testLongType(); + testDoubleType(); + testStringType(); + + + } + + protected void testBooleanType() { + + assertEquals(false, bean.isBooleanValue()); + assertFieldInError("booleanValue", "expression.boolean.not.equals##true", true); + assertFieldInError("booleanValue", "expression.boolean.not.equals##false", false); + + bean.setBooleanValue(true); + assertFieldInError("booleanValue", "expression.boolean.not.equals##true", false); + assertFieldInError("booleanValue", "expression.boolean.not.equals##false", true); + } + + protected void testShortType() { + assertEquals(0, bean.getShortValue()); + assertFieldInError("shortValue", MESSAGE, false); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 10); + assertFieldInError("shortValue", MESSAGE, false); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 1000); + assertFieldInError("shortValue", MESSAGE, true); + assertFieldInError("shortValue", MESSAGE2, false); + bean.setShortValue((short) 3000); + assertFieldInError("shortValue", MESSAGE, true); + assertFieldInError("shortValue", MESSAGE2, true); + } + + protected void testIntType() { + assertEquals(0, bean.getIntValue()); + assertFieldInError("intValue", MESSAGE, false); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(10); + assertFieldInError("intValue", MESSAGE, false); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(1000); + assertFieldInError("intValue", MESSAGE, true); + assertFieldInError("intValue", MESSAGE2, false); + bean.setIntValue(3000); + assertFieldInError("intValue", MESSAGE, true); + assertFieldInError("intValue", MESSAGE2, true); + } + + protected void testLongType() { + assertEquals(0, bean.getLongValue()); + assertFieldInError("longValue", MESSAGE, false); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(10); + assertFieldInError("longValue", MESSAGE, false); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(1000); + assertFieldInError("longValue", MESSAGE, true); + assertFieldInError("longValue", MESSAGE2, false); + bean.setLongValue(3000); + assertFieldInError("longValue", MESSAGE, true); + assertFieldInError("longValue", MESSAGE2, true); + } + + protected void testDoubleType() { + assertEquals(0.0, bean.getDoubleValue(), 0); + assertFieldInError("doubleValue", MESSAGE + ".0", false); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(10); + assertFieldInError("doubleValue", MESSAGE + ".0", false); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(1000); + assertFieldInError("doubleValue", MESSAGE + ".0", true); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", false); + bean.setDoubleValue(3000); + assertFieldInError("doubleValue", MESSAGE + ".0", true); + assertFieldInError("doubleValue", "expression.too.big##100.0##2000.0", true); + } + + protected void testStringType() { + assertEquals(null, bean.getStringValue()); + + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", true); + bean.setStringValue("100"); + + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", true); + + bean.setStringValue("1000"); + assertFieldInError("stringValue", "expression.stringNotValue##1000", false); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", false); + + bean.setStringValue("3000"); + assertFieldInError("stringValue", "expression.stringNotValue##1000", true); + assertFieldInError("stringValue", "expression.stringNotValue##1000##3000", false); + } +} \ No newline at end of file Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingDirectoryFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingDirectoryFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingDirectoryFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,7 +3,7 @@ import java.io.File; /** @author chemit */ -public class NotExistingDirectoryFieldValidatorTest extends AbstractFieldValidatorTest { +public class NotExistingDirectoryFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { @org.junit.Test @Override Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingFileFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingFileFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/NotExistingFileFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,7 +3,7 @@ import java.io.File; /** @author chemit */ -public class NotExistingFileFieldValidatorTest extends AbstractFieldValidatorTest { +public class NotExistingFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { @org.junit.Test Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/RequiredFileFieldValidatorTest.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/RequiredFileFieldValidatorTest.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/RequiredFileFieldValidatorTest.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -3,7 +3,7 @@ import java.io.File; /** @author chemit */ -public class RequiredFileFieldValidatorTest extends AbstractFieldValidatorTest { +public class RequiredFileFieldValidatorTest extends AbstractValidatorBeanFieldValidatorTest { @org.junit.Test @Override Copied: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ValidatorBean.java (from rev 1273, jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/ValidatorBean.java) =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ValidatorBean.java (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/ValidatorBean.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,149 @@ +package jaxx.runtime.validator.field; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.util.Collection; + +public class ValidatorBean { + + public static class ValidatorBeanEntry { + + protected int intValue; + protected String stringValue; + protected String stringValue2; + + public ValidatorBeanEntry(int intValue, String stringValue) { + this.intValue = intValue; + this.stringValue = stringValue; + } + + public ValidatorBeanEntry(int intValue, String stringValue, String stringValue2) { + this.intValue = intValue; + this.stringValue = stringValue; + this.stringValue2 = stringValue2; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(int intValue) { + this.intValue = intValue; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public String getStringValue2() { + return stringValue2; + } + + public void setStringValue2(String stringValue2) { + this.stringValue2 = stringValue2; + } + } + protected File existingFile; + protected File notExistingFile; + protected File existingDirectory; + protected File notExistingDirectory; + protected Collection<ValidatorBeanEntry> entries; + protected String stringValue; + protected ValidatorBeanEntry entry; + PropertyChangeSupport p; + + public ValidatorBean() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + public String getStringValue() { + return stringValue; + } + + public File getExistingFile() { + return existingFile; + } + + public File getNotExistingFile() { + return notExistingFile; + } + + public File getExistingDirectory() { + return existingDirectory; + } + + public File getNotExistingDirectory() { + return notExistingDirectory; + } + + public ValidatorBeanEntry getEntry() { + return entry; + } + + public Collection<ValidatorBeanEntry> getEntries() { + return entries; + } + + public void setStringValue(String stringValue) { + String old = this.stringValue; + this.stringValue = stringValue; + p.firePropertyChange("stringValue", old, existingFile); + } + + public void setExistingFile(File existingFile) { + File old = this.existingFile; + this.existingFile = existingFile; + p.firePropertyChange("existingFile", old, existingFile); + } + + public void setNotExistingFile(File notExistingFile) { + File old = this.notExistingFile; + this.notExistingFile = notExistingFile; + p.firePropertyChange("notExistingFile", old, notExistingFile); + } + + public void setExistingDirectory(File existingDirectory) { + File old = this.existingDirectory; + this.existingDirectory = existingDirectory; + p.firePropertyChange("existingDirectory", old, existingDirectory); + } + + public void setNotExistingDirectory(File notExistingDirectory) { + File old = this.notExistingDirectory; + this.notExistingDirectory = notExistingDirectory; + p.firePropertyChange("notExistingDirectory", old, notExistingDirectory); + } + + public void setEntries(Collection<ValidatorBeanEntry> entries) { + this.entries = entries; + // set null oldValue to always fire event + // otherwise it could been not sent... + p.firePropertyChange("entries", null, entries); + } + + public void setEntry(ValidatorBeanEntry entry) { + this.entry = entry; + p.firePropertyChange("entry", null, entry); + } +} \ No newline at end of file Deleted: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-error-validation.xml =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-error-validation.xml 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-error-validation.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -1,95 +0,0 @@ -<!DOCTYPE validators PUBLIC - "-//OpenSymphony Group//XWork Validator 1.0.2//EN" - "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> -<validators> - - <field name="stringValue"> - <field-validator type="requiredstring" short-circuit="true"> - <message>stringValue.required</message> - </field-validator> - </field> - - <field name="existingFile"> - <field-validator type="requiredFile" short-circuit="true"> - <message>existingFile.required</message> - </field-validator> - <field-validator type="existingFile" short-circuit="true"> - <message>existingFile.not.exist</message> - </field-validator> - </field> - - <field name="notExistingFile"> - <field-validator type="requiredFile" short-circuit="true"> - <message>notExistingFile.required</message> - </field-validator> - <field-validator type="notExistingFile" short-circuit="true"> - <message>notExistingFile.exist</message> - </field-validator> - </field> - - <field name="existingDirectory"> - <field-validator type="requiredFile" short-circuit="true"> - <message>existingDirectory.required</message> - </field-validator> - - <field-validator type="existingDirectory" short-circuit="true"> - <message>existingDirectory.not.exist</message> - </field-validator> - </field> - - <field name="notExistingDirectory"> - <field-validator type="requiredFile" short-circuit="true"> - <message>notExistingDirectory.required</message> - </field-validator> - - <field-validator type="notExistingDirectory" short-circuit="true"> - <message>notExistingDirectory.exist</message> - </field-validator> - </field> - - <field name="entries"> - <field-validator type="collectionFieldExpression"> - <param name="mode">AT_LEAST_ONE</param> - <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]></param> - <message>collectionFieldExpression.atLeastOne</message> - </field-validator> - <field-validator type="collectionFieldExpression"> - <param name="mode">EXACTLY_ONE</param> - <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]></param> - <message>collectionFieldExpression.exactlyOne</message> - </field-validator> - <field-validator type="collectionFieldExpression"> - <param name="mode">ALL</param> - <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]></param> - <message>collectionFieldExpression.all</message> - </field-validator> - <field-validator type="collectionFieldExpression"> - <param name="mode">NONE</param> - <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]></param> - <message>collectionFieldExpression.none</message> - </field-validator> - - <field-validator type="collectionUniqueKey"> - <param name="keys">intValue</param> - <message>collectionUniqueKey.one.failed</message> - </field-validator> - <field-validator type="collectionUniqueKey"> - <param name="keys">stringValue</param> - <message>collectionUniqueKey.two.failed</message> - </field-validator> - <field-validator type="collectionUniqueKey"> - <param name="keys">intValue,stringValue</param> - <message>collectionUniqueKey.three.failed</message> - </field-validator> - <field-validator type="collectionUniqueKey"> - <param name="keys">intValue,stringValue,stringValue2</param> - <message>collectionUniqueKey.four.failed</message> - </field-validator> - <field-validator type="collectionUniqueKey"> - <param name="keys">stringValue</param> - <param name="againstProperty">entry</param> - <message>collectionUniqueKey.five.failed</message> - </field-validator> - </field> - -</validators> \ No newline at end of file Added: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/FieldExpressionBean-error-validation.xml =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/FieldExpressionBean-error-validation.xml (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/FieldExpressionBean-error-validation.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,99 @@ +<!DOCTYPE validators PUBLIC + "-//OpenSymphony Group//XWork Validator 1.0.2//EN" + "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> +<validators> + +<field name="booleanValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="booleanParams">boolean:true</param> + <param name="expression"><![CDATA[ booleanValue == booleans.boolean]]> + </param> + <message>expression.boolean.not.equals##${booleans.boolean}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="booleanParams">boolean:false</param> + <param name="expression"><![CDATA[ booleanValue == booleans.boolean]]> + </param> + <message>expression.boolean.not.equals##${booleans.boolean}</message> + </field-validator> + </field> + + <field name="shortValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="shortParams">short:100</param> + <param name="expression"><![CDATA[ shortValue < shorts.short]]> + </param> + <message>expression.too.big##${shorts.short}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="shortParams">short:100|short2:2000</param> + <param name="expression"><![CDATA[ shortValue < shorts.short || shortValue < shorts.short2]]> + </param> + <message>expression.too.big##${shorts.short}##${shorts.short2}</message> + </field-validator> + </field> + + <field name="intValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="intParams">int:100</param> + <param name="expression"><![CDATA[ intValue < ints.int]]> + </param> + <message>expression.too.big##${ints.int}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="intParams">int:100|int2:2000</param> + <param name="expression"><![CDATA[ intValue < ints.int || intValue < ints.int2]]> + </param> + <message>expression.too.big##${ints.int}##${ints.int2}</message> + </field-validator> + </field> + + <field name="longValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="longParams">long:100</param> + <param name="expression"><![CDATA[ longValue < longs.long]]> + </param> + <message>expression.too.big##${longs.long}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="longParams">long:100|long2:2000</param> + <param name="expression"><![CDATA[ longValue < longs.long || longValue < longs.long2]]> + </param> + <message>expression.too.big##${longs.long}##${longs.long2}</message> + </field-validator> + </field> + + <field name="doubleValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="doubleParams">double:100.0</param> + <param name="expression"><![CDATA[ doubleValue < doubles.double]]> + </param> + <message>expression.too.big##${doubles.double}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="doubleParams">double:100.0|double2:2000.0</param> + <param name="expression"><![CDATA[ doubleValue < doubles.double || doubleValue < doubles.double2]]> + </param> + <message>expression.too.big##${doubles.double}##${doubles.double2}</message> + </field-validator> + </field> + + <field name="stringValue"> + <field-validator type="fieldexpressionwithparams"> + <param name="stringParams">string:1000</param> + <param name="expression"><![CDATA[ stringValue.equals(strings.string)]]> + </param> + <message>expression.stringNotValue##${strings.string}</message> + </field-validator> + <field-validator type="fieldexpressionwithparams"> + <param name="stringParams">string:1000|string2:3000</param> + <param name="expression"><![CDATA[ stringValue.equals(strings.string) || stringValue.equals(strings.string2)]]> + </param> + <message>expression.stringNotValue##${strings.string}##${strings.string2}</message> + </field-validator> + </field> + + + + +</validators> \ No newline at end of file Copied: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/ValidatorBean-error-validation.xml (from rev 1274, jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-error-validation.xml) =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/ValidatorBean-error-validation.xml (rev 0) +++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/field/ValidatorBean-error-validation.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,155 @@ +<!DOCTYPE validators PUBLIC + "-//OpenSymphony Group//XWork Validator 1.0.2//EN" + "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> +<validators> + + <field name="stringValue"> + <field-validator type="requiredstring" short-circuit="true"> + <message>stringValue.required</message> + </field-validator> + </field> + + <field name="existingFile"> + <field-validator type="requiredFile" short-circuit="true"> + <message>existingFile.required</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>existingFile.not.exist</message> + </field-validator> + </field> + + <field name="notExistingFile"> + <field-validator type="requiredFile" short-circuit="true"> + <message>notExistingFile.required</message> + </field-validator> + <field-validator type="notExistingFile" short-circuit="true"> + <message>notExistingFile.exist</message> + </field-validator> + </field> + + <field name="existingDirectory"> + <field-validator type="requiredFile" short-circuit="true"> + <message>existingDirectory.required</message> + </field-validator> + + <field-validator type="existingDirectory" short-circuit="true"> + <message>existingDirectory.not.exist</message> + </field-validator> + </field> + + <field name="notExistingDirectory"> + <field-validator type="requiredFile" short-circuit="true"> + <message>notExistingDirectory.required</message> + </field-validator> + + <field-validator type="notExistingDirectory" short-circuit="true"> + <message>notExistingDirectory.exist</message> + </field-validator> + </field> + + <field name="entries"> + + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue</param> + <message>collectionUniqueKey.one.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">stringValue</param> + <message>collectionUniqueKey.two.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue,stringValue</param> + <message>collectionUniqueKey.three.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">intValue,stringValue,stringValue2</param> + <message>collectionUniqueKey.four.failed</message> + </field-validator> + <field-validator type="collectionUniqueKey"> + <param name="keys">stringValue</param> + <param name="againstProperty">entry</param> + <message>collectionUniqueKey.five.failed</message> + </field-validator> + + <field-validator type="collectionFieldExpression"> + <param name="mode">AT_LEAST_ONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.atLeastOne</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">EXACTLY_ONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.exactlyOne</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.all</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">NONE</param> + <param name="expression"><![CDATA[ intValue == 0 && stringValue == "stringValue" ]]> + </param> + <message>collectionFieldExpression.none</message> + </field-validator> + + <!-- useContext --> + <field-validator type="collectionFieldExpression"> + <param name="mode">AT_LEAST_ONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.atLeastOne.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">EXACTLY_ONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && ( previous.intValue == 2 + current.intValue || current.intValue == 2 + previous.intValue) ]]></param> + <message>collectionFieldExpression.exactlyOne.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && (previous == null || previous.intValue < current.intValue)]]></param> + <message>collectionFieldExpression.all.useSensitiveContext</message> + </field-validator> + <field-validator type="collectionFieldExpression"> + <param name="mode">NONE</param> + <param name="useSensitiveContext">true</param> + <param name="expression"><![CDATA[ size > 1 && previous != null && ( current.intValue == 2 + previous.intValue)]]></param> + <message>collectionFieldExpression.none.useSensitiveContext</message> + </field-validator> + + <!-- useFirst --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForFirst"><![CDATA[ current.intValue == 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useFirst</message> + </field-validator> + + <!-- useLast --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForLast"><![CDATA[ current.intValue > 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useLast</message> + </field-validator> + + <!-- useFirstAndLast --> + <field-validator type="collectionFieldExpression"> + <param name="mode">ALL</param> + <param name="useSensitiveContext">true</param> + <param name="expressionForFirst"><![CDATA[ current.intValue == 0]]></param> + <param name="expressionForLast"><![CDATA[ current.intValue > 0]]></param> + <param name="expression"><![CDATA[ previous == null || previous.intValue < current.intValue]]></param> + <message>collectionFieldExpression.all.useFirstAndLast</message> + </field-validator> + + </field> + +</validators> \ No newline at end of file Modified: jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties 2009-04-04 17:05:55 UTC (rev 1291) @@ -6,3 +6,4 @@ log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n log4j.logger.jaxx=INFO +log4j.logger.jaxx.runtime.validator.field=DEBUG Modified: jaxx/trunk/jaxx-runtime-validator/src/test/resources/validators.xml =================================================================== --- jaxx/trunk/jaxx-runtime-validator/src/test/resources/validators.xml 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/validators.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -31,5 +31,6 @@ <validator name="notExistingFile" class="jaxx.runtime.validator.field.NotExistingFileFieldValidator"/> <validator name="existingDirectory" class="jaxx.runtime.validator.field.ExistingDirectoryFieldValidator"/> <validator name="notExistingDirectory" class="jaxx.runtime.validator.field.NotExistingDirectoryFieldValidator"/> + <validator name="fieldexpressionwithparams" class="jaxx.runtime.validator.field.FieldExpressionWithParamsValidator"/> </validators> \ No newline at end of file Modified: jaxx/trunk/jaxx-runtime-validator-swing/pom.xml =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/pom.xml 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator-swing/pom.xml 2009-04-04 17:05:55 UTC (rev 1291) @@ -45,6 +45,23 @@ <!-- ************************************************************* --> <packaging>jar</packaging> + <build> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <version>${i18n.version}</version> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> <!-- ************************************************************* --> <!-- *** Build Environment ************************************** --> <!-- ************************************************************* --> Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/SwingValidatorUtil.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/SwingValidatorUtil.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/SwingValidatorUtil.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -9,10 +9,13 @@ import java.awt.event.MouseListener; import javax.swing.ImageIcon; import javax.swing.JComponent; +import javax.swing.RowSorter; +import javax.swing.SortOrder; import jaxx.runtime.validator.swing.SwingValidatorMessageTableMouseListener; import jaxx.runtime.validator.swing.SwingValidatorMessageListMouseListener; import jaxx.runtime.validator.swing.SwingValidatorMessage; -import org.codelutin.i18n.I18n; +import jaxx.runtime.validator.swing.SwingValidatorMessageTableRenderer; +import static org.codelutin.i18n.I18n.n_; /** * The helper class for validation module. @@ -53,6 +56,26 @@ } /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display validators messages + */ + public static void installUI(JTable errorTable, SwingValidatorMessageTableRenderer render) { + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys(java.util.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); + } + + /** * Register for a given validator list ui a validator mouse listener. * * Note: there is only one listener registred for a given list model, so @@ -145,11 +168,11 @@ 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 (l != null) { + text = I18n._(l); + } else { + // TODO should try the text + }*/ } if (text == null) { text = value; Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -7,6 +7,7 @@ import javax.swing.DefaultListCellRenderer; import jaxx.runtime.validator.BeanValidatorScope; import jaxx.runtime.SwingValidatorUtil; +import static org.codelutin.i18n.I18n._; /** * A simple render of a table of validator's messages, says a table that use @@ -20,6 +21,7 @@ private static final long serialVersionUID = 1L; protected String format = "%1$-20s - %2$s"; + protected String formatTip = "%1$-20s - %2$-20s : %3$s"; public SwingValidatorMessageListRenderer() { } @@ -42,7 +44,7 @@ JLabel rendererComponent = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); SwingValidatorMessage model = (SwingValidatorMessage) value; - + // scope ImageIcon icon = SwingValidatorUtil.getIcon(model.getScope()); @@ -55,7 +57,15 @@ // text to display String text = String.format(format, fieldName, message); + String label = _(model.getScope().getLabel()); + String tmp = _("validator.scope.tip", label); + String tmp2 = _("validator.field.tip", fieldName); + + String tooltTipText = String.format(formatTip, tmp, tmp2, message); + + rendererComponent.setText(text); + rendererComponent.setToolTipText(tooltTipText); rendererComponent.setIcon(icon); return rendererComponent; Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java 2009-04-03 10:36:56 UTC (rev 1290) +++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java 2009-04-04 17:05:55 UTC (rev 1291) @@ -7,6 +7,7 @@ import java.awt.Component; import jaxx.runtime.validator.BeanValidatorScope; import jaxx.runtime.SwingValidatorUtil; +import static org.codelutin.i18n.I18n._; /** * A simple render of a table of validator's messages, says a table that use @@ -26,30 +27,38 @@ ImageIcon icon = null; String text = null; + String toolTipText = null; column = table.convertColumnIndexToModel(column); if (table.getRowSorter() != null) { row = table.getRowSorter().convertRowIndexToModel(row); } + switch (column) { case 0: - // scope - icon = SwingValidatorUtil.getIcon((BeanValidatorScope) value); + // scope + BeanValidatorScope scope = (BeanValidatorScope) value; + icon = SwingValidatorUtil.getIcon(scope); + String label = _(scope.getLabel()); + toolTipText = _("validator.scope.tip", label); break; case 1: // field name text = getFieldName(table, (String) value, row); + toolTipText = _("validator.field.tip", text); break; case 2: // message text = getMessage(table, (String) value, row); + toolTipText = _("validator.message.tip", text); break; } rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); rendererComponent.setIcon(icon); return rendererComponent; } Added: jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-en_GB.properties =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-en_GB.properties (rev 0) +++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-en_GB.properties 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,9 @@ +validator.field.header=Property +validator.field.header.tip=Property on which message occurs +validator.field.tip=Property '%1$s' +validator.message.header=Message +validator.message.header.tip=The message text +validator.message.tip=Message \: %1$s +validator.scope.header=... +validator.scope.header.tip=The message scope +validator.scope.tip=Message scope \: '%1$s' Added: jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-fr_FR.properties =================================================================== --- jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-fr_FR.properties (rev 0) +++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/i18n/jaxx-runtime-validator-swing-fr_FR.properties 2009-04-04 17:05:55 UTC (rev 1291) @@ -0,0 +1,9 @@ +validator.field.header=Champ +validator.field.header.tip=Le champ surquel intervient le message +validator.field.tip=Propri\u00E9t\u00E9 '%1$s' +validator.message.header=Message +validator.message.header.tip=Le texte du message +validator.message.tip=Message \: %1$s +validator.scope.header=... +validator.scope.header.tip=Le de type de message +validator.scope.tip=Type de message \: '%1$s'
participants (1)
-
tchemit@users.labs.libre-entreprise.org