Commits

Anonymous committed f846c07

WW-501
- VisitorFieldValidator loses original TextProvider

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/xwork_1-2@1537e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (5)

src/java/com/opensymphony/xwork/validator/CompositeTextProvider.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.TextProvider;
+import com.opensymphony.xwork.util.OgnlValueStack;
+
+import java.util.*;
+
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+/**
+ * This is a composite {@link TextProvider} that takes in an array or {@link List} of {@link TextProvider}s, it will
+ * consult each of them in order to get a composite result. To know how each method behaves, please refer to the
+ * javadoc for each methods.
+ *
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class CompositeTextProvider implements TextProvider {
+
+    private static final Log LOG = LogFactory.getLog(CompositeTextProvider.class);
+
+    private List textProviders = new ArrayList();
+
+    /**
+     * Instantiates a {@link CompositeTextProvider} with some predefined <code>textProviders</code>.
+     * @param textProviders
+     */
+    public CompositeTextProvider(List textProviders) {
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            Object obj = i.next();
+            if (obj instanceof TextProvider) {
+                this.textProviders.add(obj);
+            }
+            else {
+                LOG.warn("object ["+obj+"] provided in list ["+textProviders+"] is not a TextProvider instance, ignoring it");
+            }
+        }
+    }
+
+    /**
+     * Instantiates a {@link CompositeTextProvider} with some predefined <code>textProviders</code>.
+     * @param textProviders
+     */
+    public CompositeTextProvider(TextProvider[] textProviders) {
+        this(Arrays.asList(textProviders));
+    }
+
+    /**
+     * @see {@link com.opensymphony.xwork.TextProvider#hasKey(String)}
+     * It will consult each individual {@link TextProvider}s and return true if either one of the
+     * {@link TextProvider} has such a <code>key></code> else false.
+     *
+     * @param key
+     * @return
+     */
+    public boolean hasKey(String key) {
+        // if there's a key in either text providers we are ok, else try the next text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            if (_textProvider.hasKey(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String)}
+     * @param key
+     * @return
+     */
+    public String getText(String key) {
+        return getText(key, key, Collections.EMPTY_LIST);
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code> before returning <code>defaultValue</code> if every else fails.
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String)} 
+     * @param key
+     * @param defaultValue
+     * @return
+     */
+    public String getText(String key, String defaultValue) {
+        return getText(key, defaultValue, Collections.EMPTY_LIST);
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     * if every else fails.
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String, String)}
+     * @param key
+     * @param defaultValue
+     * @param obj
+     * @return
+     */
+    public String getText(String key, String defaultValue, final String obj) {
+        return getText(key, defaultValue, new ArrayList() {
+            {
+                add(obj);
+            }
+        });
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>.
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, java.util.List)}
+     * @param key
+     * @param args
+     * @return
+     */
+    public String getText(String key, List args) {
+        return getText(key, key, args);
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>.
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String[])}
+     * @param key
+     * @param args
+     * @return
+     */
+    public String getText(String key, String[] args) {
+        return getText(key, key, args);
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     * @see {@link com.opensymphony.xwork.TextProvider#getText#getText(String, String, java.util.List)}
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @return
+     */
+    public String getText(String key, String defaultValue, List args) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            String msg = _textProvider.getText(key, defaultValue, args);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>.
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String, String[])}
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @return
+     */
+    public String getText(String key, String defaultValue, String[] args) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            String msg = _textProvider.getText(key, defaultValue, args);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     *
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String, java.util.List, com.opensymphony.xwork.util.OgnlValueStack)}
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @param stack
+     * @return
+     */
+    public String getText(String key, String defaultValue, List args, OgnlValueStack stack) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            String msg = _textProvider.getText(key, defaultValue, args, stack);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first valid message for this
+     * <code>key</code>, before returining <code>defaultValue</code>
+     * @see {@link com.opensymphony.xwork.TextProvider#getText(String, String, String[], com.opensymphony.xwork.util.OgnlValueStack)}
+     * @param key
+     * @param defaultValue
+     * @param args
+     * @param stack
+     * @return
+     */
+    public String getText(String key, String defaultValue, String[] args, OgnlValueStack stack) {
+        // if there's one text provider that gives us a msg not the same as defaultValue
+        // for this key, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            String msg = _textProvider.getText(key, defaultValue, args, stack);
+            if (msg != null && (!msg.equals(defaultValue))) {
+                return msg;
+            }
+        }
+        return defaultValue;
+    }
+
+
+    /**
+     * It will consult each {@link TextProvider}s and return the first non-null {@link ResourceBundle}.
+     * @see {@link TextProvider#getTexts(String)} 
+     * @param bundleName
+     * @return
+     */
+    public ResourceBundle getTexts(String bundleName) {
+        // if there's one text provider that gives us a non-null resource bunlde for this bundleName, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            ResourceBundle bundle  = _textProvider.getTexts(bundleName);
+            if (bundle != null) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * It will consult each {@link com.opensymphony.xwork.TextProvider}s and return the first non-null {@link ResourceBundle}.
+     * @see {@link TextProvider#getTexts()} 
+     * @return
+     */
+    public ResourceBundle getTexts() {
+        // if there's one text provider that gives us a non-null resource bundle, we are ok, else try the next
+        // text provider
+        for (Iterator i = textProviders.iterator(); i.hasNext(); ) {
+            TextProvider _textProvider = (TextProvider) i.next();
+            ResourceBundle bundle = _textProvider.getTexts();
+            if (bundle != null) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+}

src/java/com/opensymphony/xwork/validator/DelegatingValidatorContext.java

         if (object instanceof TextProvider) {
             return (TextProvider) object;
         } else {
-            return new TextProviderSupport(object.getClass(), localeProvider);
+            // the object argument passed through here will most probably be an ActionSupport decendant which does
+            // implements TextProvider.
+            if ((object != null) && (object instanceof TextProvider)) {
+                 return new CompositeTextProvider(new TextProvider[] {
+                                ((TextProvider) object),
+                                new TextProviderSupport(object.getClass(), localeProvider)
+                            });
+            }
+            else {
+                return new TextProviderSupport(object.getClass(), localeProvider);
+            }
         }
     }
 

src/test/com/opensymphony/xwork/validator/CompositeTextProviderTest.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.XWorkTestCase;
+import com.opensymphony.xwork.TextProvider;
+import com.opensymphony.xwork.TextProviderSupport;
+import com.opensymphony.xwork.LocaleProvider;
+
+import java.util.ResourceBundle;
+import java.util.Locale;
+import java.util.ArrayList;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class CompositeTextProviderTest extends XWorkTestCase {
+
+
+    private CompositeTextProvider textProvider = null;
+
+
+    public void testGetText() throws Exception {
+        // we should get the text from the 1st text provider
+        assertEquals(textProvider.getText("name"), "1 name");
+        assertEquals(textProvider.getText("age"), "1 age");
+        assertEquals(textProvider.getText("dog"), "This is a dog");
+        assertEquals(textProvider.getText("cat"), "This is a cat");
+        assertEquals(textProvider.getText("car"), "This is a car");
+        assertEquals(textProvider.getText("bike"), "This is a bike");
+        assertEquals(textProvider.getText("someNonExistingKey"), "someNonExistingKey");
+    }
+
+
+    public void testGetTextWithDefaultValues() throws Exception {
+        assertEquals(textProvider.getText("name", "some default name"), "1 name");
+        assertEquals(textProvider.getText("age", "some default age"), "1 age");
+        assertEquals(textProvider.getText("no_such_key", "default value"), "default value");
+        assertEquals(textProvider.getText("dog", "some default dog"), "This is a dog");
+        assertEquals(textProvider.getText("cat", "some default cat"), "This is a cat");
+        assertEquals(textProvider.getText("car", "some default car"), "This is a car");
+        assertEquals(textProvider.getText("bike", "some default bike"), "This is a bike");
+    }
+
+
+    public void testGetTextWithDefaultValuesAndArgs() throws Exception {
+        assertEquals(textProvider.getText("goodnight", "say good night", "Adam"), "1 good night Adam");
+        assertEquals(textProvider.getText("goodnight", "say good night", new String[] { "Adam" }), "1 good night Adam");
+        assertEquals(textProvider.getText("goodnight", "say good night", new ArrayList() { {add("Adam");} }), "1 good night Adam");
+        assertEquals(textProvider.getText("goodmorning", "say good morning", new String[] { "Jack", "Jim" }), "1 good morning Jack and Jim");
+        assertEquals(textProvider.getText("goodmorning", "say good morning", new ArrayList() { { add("Jack"); add("Jim"); }}), "1 good morning Jack and Jim");
+    }
+
+    public void testHasKey() throws Exception {
+        assertTrue(textProvider.hasKey("name"));
+        assertTrue(textProvider.hasKey("age"));
+        assertTrue(textProvider.hasKey("cat"));
+        assertTrue(textProvider.hasKey("dog"));
+        assertTrue(textProvider.hasKey("car"));
+        assertTrue(textProvider.hasKey("bike"));
+        assertTrue(textProvider.hasKey("goodnight"));
+        assertTrue(textProvider.hasKey("goodmorning"));
+        assertFalse(textProvider.hasKey("nosuchkey"));
+    }
+
+    public void testGetResourceBundleByName() throws Exception {
+        assertNotNull(textProvider.getTexts("com.opensymphony.xwork.validator.CompositeTextProviderTestResourceBundle1"));
+        assertNotNull(textProvider.getTexts("com.opensymphony.xwork.validator.CompositeTextProviderTestResourceBundle2"));
+        assertNull(textProvider.getTexts("com.opensymphony.xwork.validator.CompositeTextProviderTestResourceBundle3"));
+    }
+
+    public void testGetResourceBundle() throws Exception {
+        assertNotNull(textProvider.getTexts());
+        // we should get the first resource bundle where 'car' and 'bike' has a i18n msg
+        assertNotNull(textProvider.getTexts().getString("car"));
+        assertNotNull(textProvider.getTexts().getString("bike"));
+    }
+
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        textProvider = new CompositeTextProvider(new TextProvider[] {
+                new TextProviderSupport(ResourceBundle.getBundle("com.opensymphony.xwork.validator.CompositeTextProviderTestResourceBundle1"),
+                        new LocaleProvider() {
+                            public Locale getLocale() {
+                                return Locale.ENGLISH;
+                            }
+                        }),
+                new TextProviderSupport(ResourceBundle.getBundle("com.opensymphony.xwork.validator.CompositeTextProviderTestResourceBundle2"),
+                        new LocaleProvider() {
+                            public Locale getLocale() {
+                                return Locale.ENGLISH;        
+                            }
+                        })
+
+        });
+    }
+
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        textProvider = null;
+    }
+}

src/test/com/opensymphony/xwork/validator/CompositeTextProviderTestResourceBundle1.properties

+# common in both CompositeTextProviderTestResourceBundle1.properties
+# and CompositeTextProviderTestResourceBunlde2.properties
+name=1 name
+age=1 age
+goodnight=1 good night {0}
+goodmorning=1 good morning {0} and {1}
+
+# specific to CompositeTextProviderTestResourceBundle1.properties
+car=This is a car
+bike=This is a bike

src/test/com/opensymphony/xwork/validator/CompositeTextProviderTestResourceBundle2.properties

+# common in both CompositeTextProviderTestResourceBundle1.properties
+# and CompositeTextProviderTestResourceBunlde2.properties
+name=2 name
+age=2 age
+goodnight=2 good night {0}
+goodmorning=2 good morning {0} and {1}
+
+
+# specific to CompositeTextProviderTestResourceBundle2.properties
+cat=This is a cat
+dog=This is a dog