You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Mattias J <ma...@expertsystem.se> on 2005/05/19 09:13:14 UTC

[i18n PATCH] Adding provider qualifying

I have previously discussed with Daniel Florey a change that allows the user to qualify the provider (or source or namespace) to be used for a given text entry. My main motivation for this is to allow the same entry key in several different text sources, but this also provides better performance since the API does not have to loop over the different providers in search for the given entry.

Thanks to James Mitchell I am now able to create the diff for this change; see below. I would be happy if Daniel or anybody else would review and commit this patch.

Included in the patch is also a minor change that allows non-string ResourceBundle entries to be used (via toString()).

After this there are a few more changes I would like to discuss - conserning class and package dependencies among others - so Daniel, please tell me when you are available again. I also hope to find the time to create an example DatabaseProvider.

Now here is the diff.
(Again, if lines are wrapped in the e-mail, I can provide the diff by personal e-mail or in a bugzilla entry).

Index: src/test/org/apache/commons/i18n/MockProviderTestBase.java
===================================================================
--- src/test/org/apache/commons/i18n/MockProviderTestBase.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/MockProviderTestBase.java	(working copy)
@@ -30,36 +30,41 @@
  * @author Mattias Jiderhamn
  */
 public abstract class MockProviderTestBase extends TestCase {
-    /**
-     * Mock message provider that returns a string made up of the arguments passed to it.
-     */
-    final private MessageProvider mockMessageProvider = new MessageProvider() {
-        public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
-            return MockProviderTestBase.getMockString(id, entry, locale);
-        }
 
-        public Map getEntries(String id, Locale locale) throws MessageNotFoundException {
-            Map output = new HashMap();
-            output.put("entry1", MockProviderTestBase.getMockString(id,"entry1",locale));
-            output.put("entry2", MockProviderTestBase.getMockString(id,"entry2",locale));
-            return output;
-        }
-    };
-
     public void tearDown() {
         /* Remove mock provider after each test, to allow for MessageNotFoundExceptions */
-        MessageManager.removeMessageProvider("mock");
-        removeThrowingMockProvider();
+        MessageManager.clearMessageProviders();
     }
 
     /**
      * Add mock provider to <code>MessageManager</code>.
      */
     protected void addMockProvider() {
-        MessageManager.addMessageProvider("mock", mockMessageProvider);
+        addMockProvider("mock");
     }
 
     /**
+     * Add mock provider to <code>MessageManager</code>.
+     */
+    protected void addMockProvider(final String providerId) {
+         //  Mock message provider that returns a string made up of the arguments passed to it.
+        MessageProvider mockMessageProvider = new MessageProvider() {
+            public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
+                return MockProviderTestBase.getMockString(providerId, id, entry, locale);
+            }
+
+            public Map getEntries(String id, Locale locale) throws MessageNotFoundException {
+                Map output = new HashMap();
+                output.put("entry1", MockProviderTestBase.getMockString(providerId,id,"entry1",locale));
+                output.put("entry2", MockProviderTestBase.getMockString(providerId,id,"entry2",locale));
+                return output;
+            }
+        };
+
+        MessageManager.addMessageProvider(providerId, mockMessageProvider);
+    }
+
+    /**
      * Add provider that always throws error to <code>MessageManager</code>.
      */
     protected void addThrowingMockProvider() {
@@ -82,10 +87,19 @@
     // Utility methods
     ////////////////////////////////////////////////////////////////////////
 
+    public static String getMockString(String providerId, String id, String entry, Locale locale) throws MessageNotFoundException {
+        return ((providerId != null) ? "Source=" + providerId + " " : "") +
+                "Id=" + id + " Entry=" + entry + " Locale=" + locale + "";
+    }
+
     public static String getMockString(String id, String entry, Locale locale) throws MessageNotFoundException {
-        return "Id=" + id + " Entry=" + entry + " Locale=" + locale + "";
+        return getMockString("mock", id, entry, locale);
     }
 
+    public static String getFormattedMockString(String providerId, String id, String entry, String[] arguments, Locale locale) {
+        return MessageFormat.format(getMockString(providerId, id, entry, locale), arguments);
+    }
+
     public static String getFormattedMockString(String id, String entry, String[] arguments, Locale locale) {
         return MessageFormat.format(getMockString(id, entry, locale), arguments);
     }
Index: src/test/org/apache/commons/i18n/MessageManagerTest.java
===================================================================
--- src/test/org/apache/commons/i18n/MessageManagerTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/MessageManagerTest.java	(working copy)
@@ -55,26 +55,48 @@
 
         addMockProvider(); // Add mock provider
 
-        assertEquals("Throwing mock not used", "Id=dummyId Entry=dummyEntry Locale=en_US",
+        assertEquals("Throwing mock not used", "Source=mock Id=dummyId Entry=dummyEntry Locale=en_US",
                 MessageManager.getText("dummyId", "dummyEntry", null, Locale.US, "defaultText"));
 
         removeThrowingMockProvider(); // Removing throwing mock and keep only normal mock
 
-        assertEquals("Default text not used", "Id=dummyId Entry=dummyEntry Locale=en_US",
+        assertEquals("Default text not used", "Source=mock Id=dummyId Entry=dummyEntry Locale=en_US",
                 MessageManager.getText("dummyId", "dummyEntry", null, Locale.US, "defaultText"));
 
-        assertEquals("Normal lookup", "Id=id Entry=entry Locale=en_US",
+        assertEquals("Normal lookup", "Source=mock Id=id Entry=entry Locale=en_US",
                 MessageManager.getText("id", "entry", null, Locale.US));
         assertEquals("Single argument",
-                "Id=id Entry=entry value1 Locale=en_US",
+                "Source=mock Id=id Entry=entry value1 Locale=en_US",
                 MessageManager.getText("id", "entry {0}", new String[] {"value1"}, Locale.US));
         assertEquals("Multiple arguments",
-                "Id=id Entry=entry value0: value1 Locale=en_US",
+                "Source=mock Id=id Entry=entry value0: value1 Locale=en_US",
                 MessageManager.getText("id", "entry {0}: {1}", new String[] {"value0", "value1"},Locale.US));
 
         assertEquals("Single argument and default",
-                "Id=id Entry=entry value1 Locale=en_US",
+                "Source=mock Id=id Entry=entry value1 Locale=en_US",
                 MessageManager.getText("id", "entry {0}", new String[] {"value1"},Locale.US, "defaultText"));
+
+        // Named provider not found
+        try {
+            MessageManager.getText("mockProvider2", "dummyId", "dummyEntry", null, Locale.US);
+            fail("Unknown provider should throw Exception");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Error text", "Provider 'mockProvider2' not installed", mnfex.getMessage());
+        }
+
+        assertEquals("Default text used", "defaultText",
+                MessageManager.getText("mockProvider2", "dummyId", "dummyEntry", null, Locale.US, "defaultText"));
+
+
+        // Named provider found
+        addMockProvider("mockProvider2");
+
+        assertEquals("Default text not used, qualified lookup", "Source=mockProvider2 Id=dummyId Entry=dummyEntry Locale=en_US",
+                MessageManager.getText("mockProvider2", "dummyId", "dummyEntry", null, Locale.US, "defaultText"));
+
+        assertEquals("Normal qualified lookup", "Source=mockProvider2 Id=id Entry=entry Locale=en_US",
+                MessageManager.getText("mockProvider2", "id", "entry", null, Locale.US));
     }
 
     public void testGetEntries() {
@@ -100,8 +122,8 @@
 
         Map entries = MessageManager.getEntries("dummyId", Locale.US);
         assertEquals("No of entries", 2, entries.size());
-        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1 Locale=en_US", entries.get("entry1"));
-        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2 Locale=en_US", entries.get("entry2"));
+        assertEquals("Entry 1 match", "Source=mock Id=dummyId Entry=entry1 Locale=en_US", entries.get("entry1"));
+        assertEquals("Entry 2 match", "Source=mock Id=dummyId Entry=entry2 Locale=en_US", entries.get("entry2"));
 
         removeThrowingMockProvider(); // Removing throwing mock and keep only normal mock
 
@@ -109,7 +131,24 @@
 
         entries = MessageManager.getEntries("dummyId", Locale.US);
         assertEquals("No of entries", 2, entries.size());
-        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1 Locale=en_US", entries.get("entry1"));
-        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2 Locale=en_US", entries.get("entry2"));
+        assertEquals("Entry 1 match", "Source=mock Id=dummyId Entry=entry1 Locale=en_US", entries.get("entry1"));
+        assertEquals("Entry 2 match", "Source=mock Id=dummyId Entry=entry2 Locale=en_US", entries.get("entry2"));
+
+        // Named provider not found
+        try {
+            MessageManager.getEntries("mockProvider2", "dummyId", Locale.US);
+            fail("Unknown provider should throw Exception");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Error text", "Provider 'mockProvider2' not installed", mnfex.getMessage());
+        }
+
+        // Named provider found
+        addMockProvider("mockProvider2");
+
+        entries = MessageManager.getEntries("mockProvider2", "dummyId", Locale.US);
+        assertEquals("No of entries", 2, entries.size());
+        assertEquals("Entry 1 match", "Source=mockProvider2 Id=dummyId Entry=entry1 Locale=en_US", entries.get("entry1"));
+        assertEquals("Entry 2 match", "Source=mockProvider2 Id=dummyId Entry=entry2 Locale=en_US", entries.get("entry2"));
     }
 }
\ No newline at end of file
Index: src/test/org/apache/commons/i18n/LocalizedBundleTest.java
===================================================================
--- src/test/org/apache/commons/i18n/LocalizedBundleTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/LocalizedBundleTest.java	(working copy)
@@ -24,21 +24,38 @@
 public class LocalizedBundleTest extends MockProviderTestBase {
     public void testConstructors() {
         LocalizedBundle lb = new LocalizedBundle("dummyId1");
+        assertNull("No provider", lb.getProviderId());
         assertEquals("Id set", "dummyId1", lb.getId());
         assertNotNull("Arguments not null", lb.getArguments());
         assertEquals("No arguments", 0, lb.getArguments().length);
 
+        LocalizedBundle lbProvider = new LocalizedBundle("dummyProvider2", "dummyId2");
+        assertEquals("Provider set", "dummyProvider2", lbProvider.getProviderId());
+        assertEquals("Id set", "dummyId2", lbProvider.getId());
+        assertNotNull("Arguments not null", lbProvider.getArguments());
+        assertEquals("No arguments", 0, lbProvider.getArguments().length);
+
         String[] arguments = new String[]{"arg1", "arg2"};
-        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", arguments);
-        assertEquals("Id set", "dummyId2", lbArgs.getId());
+        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", arguments);
+        assertNull("No provider", lbArgs.getProviderId());
+        assertEquals("Id set", "dummyId3", lbArgs.getId());
         assertNotNull("Arguments not null", lbArgs.getArguments());
         assertEquals("No of arguments", 2, lbArgs.getArguments().length);
         assertEquals("Arguments", arguments, lbArgs.getArguments());
+
+        LocalizedBundle lbProviderArgs = new LocalizedBundle("dummyProvider4", "dummyId4", arguments);
+        assertEquals("Provider set", "dummyProvider4", lbProviderArgs.getProviderId());
+        assertEquals("Id set", "dummyId4", lbProviderArgs.getId());
+        assertNotNull("Arguments not null", lbProviderArgs.getArguments());
+        assertEquals("No of arguments", 2, lbProviderArgs.getArguments().length);
+        assertEquals("Arguments", arguments, lbProviderArgs.getArguments());
     }
 
     public void testGetEntry() {
         LocalizedBundle lb = new LocalizedBundle("dummyId1");
-        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", new String[] {"arg1", "arg2"});
+        LocalizedBundle lbProvider = new LocalizedBundle("dummyProvider2", "dummyId2");
+        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", new String[] {"arg1", "arg2"});
+        LocalizedBundle lbProviderArgs = new LocalizedBundle("dummyProvider4", "dummyId4", new String[] {"arg1", "arg2"});
 
         // Test errors
         try {
@@ -63,15 +80,53 @@
 
         addMockProvider(); // Add mock provider
 
-        assertEquals("Default text not used", "Id=dummyId1 Entry=dummyEntry Locale=en_US",
+        assertEquals("Default text not used", getMockString("dummyId1", "dummyEntry", Locale.US),
                 lb.getEntry("dummyEntry", Locale.US, "defaltText"));
 
-        assertEquals("Normal lookup", "Id=dummyId1 Entry=entry Locale=en_US", lb.getEntry("entry", Locale.US));
-        assertEquals("Arguments missing", "Id=dummyId1 Entry=entry {0} Locale=en_US",
+        assertEquals("Normal lookup", getMockString("dummyId1", "entry", Locale.US), lb.getEntry("entry", Locale.US));
+        assertEquals("Arguments missing", "Source=mock Id=dummyId1 Entry=entry {0} Locale=en_US",
                 lb.getEntry("entry {0}", Locale.US));
-        assertEquals("Argument", "Id=dummyId2 Entry=entry arg1 arg2 Locale=en_US",
+        assertEquals("Argument", "Source=mock Id=dummyId3 Entry=entry arg1 arg2 Locale=en_US",
                 lbArgs.getEntry("entry {0} {1}", Locale.US));
-        assertEquals("Arguments and default", "Id=dummyId2 Entry=entry arg1 arg2 Locale=en_US",
+        assertEquals("Arguments and default", "Source=mock Id=dummyId3 Entry=entry arg1 arg2 Locale=en_US",
                 lbArgs.getEntry("entry {0} {1}", Locale.US, "defaultText"));
+
+        // Named provider not found
+        try {
+            lbProvider.getEntry("dummyEntry", Locale.US);
+            fail("Unknown provider should throw Exception");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Error text", "Provider 'dummyProvider2' not installed", mnfex.getMessage());
+        }
+
+        try {
+            lbProviderArgs.getEntry("dummyEntry", Locale.US);
+            fail("Unknown provider should throw Exception");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Error text", "Provider 'dummyProvider4' not installed", mnfex.getMessage());
+        }
+
+        assertEquals("Default text", "defaultText", lbProvider.getEntry("dummyEntry", Locale.US, "defaultText"));
+        assertEquals("Default text", "defaultText", lbProviderArgs.getEntry("dummyEntry", Locale.US, "defaultText"));
+
+        // Named provider found
+        addMockProvider("dummyProvider2");
+        addMockProvider("dummyProvider4");
+
+        assertEquals("Named provider: Default text not used",
+                getMockString("dummyProvider2", "dummyId2", "dummyEntry", Locale.US),
+                lbProvider.getEntry("dummyEntry", Locale.US, "defaltText"));
+
+        assertEquals("Named provider: Normal lookup", getMockString("dummyProvider2", "dummyId2", "entry", Locale.US),
+                lbProvider.getEntry("entry", Locale.US));
+        assertEquals("Named provider: Arguments missing", "Source=dummyProvider2 Id=dummyId2 Entry=entry {0} Locale=en_US",
+                lbProvider.getEntry("entry {0}", Locale.US));
+        assertEquals("Named provider: Argument", "Source=dummyProvider4 Id=dummyId4 Entry=entry arg1 arg2 Locale=en_US",
+                lbProviderArgs.getEntry("entry {0} {1}", Locale.US));
+        assertEquals("Named provider: Arguments and default",
+                "Source=dummyProvider4 Id=dummyId4 Entry=entry arg1 arg2 Locale=en_US",
+                lbProviderArgs.getEntry("entry {0} {1}", Locale.US, "defaultText"));
     }
 }
Index: src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
===================================================================
--- src/test/org/apache/commons/i18n/XMLMessageProviderTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/XMLMessageProviderTest.java	(working copy)
@@ -2,7 +2,7 @@
 *
 * ====================================================================
 *
-* Copyright 2004 The Apache Software Foundation
+* Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -56,12 +56,12 @@
         }
 
         XMLMessageProvider.install("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
 
         assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
 
         XMLMessageProvider.update("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
 
         assertEquals("OK after update", "Hallo Welt", testMessage.getTitle(Locale.GERMAN));
 
@@ -77,14 +77,14 @@
 
         // Try to parse non-XML file
         XMLMessageProvider.install("org.apache.commons-i18n.error",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
     }
-
+    
     public void testGetText() {
 //        XMLMessageProvider.install("org.apache.commons-i18n.test",
-// Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+//                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
         XMLMessageProvider xmlmp = new XMLMessageProvider("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
 
         assertEquals("Default locale", "hello world", xmlmp.getText("helloWorld", "title", Locale.US));
         assertEquals("Default locale", "hello world", xmlmp.getText("helloWorld", "title", Locale.UK));
@@ -123,9 +123,9 @@
 
     public void testGetTextVariants() {
 //        XMLMessageProvider.install("org.apache.commons-i18n.variants",
-// Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
+//                Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
         XMLMessageProvider xmlmp = new XMLMessageProvider("org.apache.commons-i18n.variants",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
 
         assertEquals("hello world", xmlmp.getText("variants", "theKey", Locale.ENGLISH));
         assertEquals("Botswana", "Hello Botswana", xmlmp.getText("variants", "theKey", new Locale("", "BW")));
@@ -135,9 +135,9 @@
 
     public void testGetEntries() {
 //        XMLMessageProvider.install("org.apache.commons-i18n.test",
-// Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
+//                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
         Map usEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
                     getEntries("helloWorld", Locale.US);
         assertEquals("Default locale, no of entries", 5, usEntries.size());
         assertEquals("Default locale, titel", "hello world", usEntries.get("title"));
@@ -151,7 +151,7 @@
         assertEquals("This entry is not translated to any other languages (XML)", usEntries.get("notTranslated"));
 
         Map germanEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
                     getEntries("helloWorld", Locale.GERMAN);
         assertEquals("No of entries", 4, germanEntries.size());
         assertEquals("Hallo Welt", germanEntries.get("title"));
@@ -163,7 +163,7 @@
 //        assertEquals("This entry is not translated to any other languages", germanEntries.get("notTranslated"));
 
         Map japaneseEntries = new XMLMessageProvider("org.apache.commons-i18n.test",
- Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
+                Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
                     getEntries("helloWorld", Locale.JAPANESE);
         assertEquals("Fallback locale, no of entries", 5, japaneseEntries.size());
 
Index: src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
===================================================================
--- src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java	(working copy)
@@ -2,7 +2,7 @@
 *
 * ====================================================================
 *
-* Copyright 2004 The Apache Software Foundation
+* Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@
         ResourceBundleMessageProvider.uninstall("messageBundle");
         ResourceBundleMessageProvider.uninstall("messageBundle2");
         ResourceBundleMessageProvider.uninstall("nonExistentBundle");
- ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListResourceBundle");
+        ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListResourceBundle");
     }
 
     public void testInstallResourceBundle() {
@@ -89,17 +89,11 @@
 
         // Test with list resource bundle
 //        ResourceBundleMessageProvider.uninstall("messageBundle"); // Remove
-// ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResourceBundle"); // Install ListResourceBundle
+//        ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResourceBundle"); // Install ListResourceBundle
         ResourceBundleMessageProvider listResourceBundleProvider =
                 new ResourceBundleMessageProvider("org.apache.commons.i18n.MyListResourceBundle"); // Install ListResourceBundle
         assertEquals("Value from ListResourceBundle", "listResourceValue", listResourceBundleProvider.getText("helloWorld", "title", Locale.US));
-        try {
-            String s = listResourceBundleProvider.getText("helloWorld", "text", Locale.US);
-            fail("Entry should not be found, since it is numeric. Found text: " + s);
-        }
-        catch(MessageNotFoundException mnfex) {
-            assertEquals("No message entries found for bundle with key helloWorld", mnfex.getMessage());
-        }
+        assertEquals("Value from ListResourceBundle", "1", listResourceBundleProvider.getText("helloWorld", "text", Locale.US));
 
         try {
             rbmp.getText("nonExistentId", "nonExistentEntry", Locale.US);
Index: src/test/org/apache/commons/i18n/I18nTestSuite.java
===================================================================
--- src/test/org/apache/commons/i18n/I18nTestSuite.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/I18nTestSuite.java	(working copy)
@@ -2,7 +2,7 @@
 *
 * ====================================================================
 *
-* Copyright 2004 The Apache Software Foundation
+* Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
Index: src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
===================================================================
--- src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java	(working copy)
@@ -52,6 +52,38 @@
                 eb.getDetails(Locale.US, "defaultText"));
     }
 
+    public void testWithProvider() {
+        addMockProvider(); // Add wrong provider
+        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId");
+        try {
+            eb.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText", eb.getText(Locale.US, "defaultText"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", ErrorBundle.TEXT, Locale.US),
+                eb.getText(Locale.US));
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", ErrorBundle.TITLE, Locale.US),
+                eb.getTitle(Locale.US));
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", ErrorBundle.SUMMARY, Locale.US),
+                eb.getSummary(Locale.US));
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", ErrorBundle.DETAILS, Locale.US),
+                eb.getDetails(Locale.US));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", ErrorBundle.TEXT, Locale.US),
+                eb.getText(Locale.US, "defaultText"));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", ErrorBundle.TITLE, Locale.US),
+                eb.getTitle(Locale.US, "defaultText"));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", ErrorBundle.SUMMARY, Locale.US),
+                eb.getSummary(Locale.US, "defaultText"));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", ErrorBundle.DETAILS, Locale.US),
+                eb.getDetails(Locale.US, "defaultText"));
+    }
+
     public void testWithArguments() {
         String[] arguments = new String[]{"arg1", "arg2"};
         ErrorBundle eb = new ErrorBundle("dummyId", arguments);
@@ -83,4 +115,45 @@
         assertEquals("Default not used", getFormattedMockString("dummyId", ErrorBundle.DETAILS, arguments, Locale.US),
                 eb.getDetails(Locale.US, "defaultText"));
     }
+
+    public void testWithProviderAndArguments() {
+        addMockProvider(); // Add wrong provider
+        String[] arguments = new String[]{"arg1", "arg2"};
+        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId", arguments);
+        try {
+            eb.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText arg1 arg2", eb.getText(Locale.US, "defaultText {0} {1}"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.TEXT, arguments, Locale.US),
+                eb.getText(Locale.US));
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.TITLE, arguments, Locale.US),
+                eb.getTitle(Locale.US));
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.SUMMARY, arguments, Locale.US),
+                eb.getSummary(Locale.US));
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.DETAILS, arguments, Locale.US),
+                eb.getDetails(Locale.US));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.TEXT, arguments, Locale.US),
+                eb.getText(Locale.US, "defaultText"));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.TITLE, arguments, Locale.US),
+                eb.getTitle(Locale.US, "defaultText"));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.SUMMARY, arguments, Locale.US),
+                eb.getSummary(Locale.US, "defaultText"));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", ErrorBundle.DETAILS, arguments, Locale.US),
+                eb.getDetails(Locale.US, "defaultText"));
+    }
 }
\ No newline at end of file
Index: src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
===================================================================
--- src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java	(working copy)
@@ -46,6 +46,30 @@
                 mb.getTitle(Locale.US, "defaultText"));
     }
 
+    public void testWithProvider() {
+        addMockProvider(); // Add wrong provider
+        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId");
+        try {
+            mb.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText", mb.getText(Locale.US, "defaultText"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", MessageBundle.TEXT, Locale.US),
+                mb.getText(Locale.US));
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", MessageBundle.TITLE, Locale.US),
+                mb.getTitle(Locale.US));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", MessageBundle.TEXT, Locale.US),
+                mb.getText(Locale.US, "defaultText"));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", MessageBundle.TITLE, Locale.US),
+                mb.getTitle(Locale.US, "defaultText"));
+    }
+
     public void testWithArguments() {
         String[] arguments = new String[]{"arg1", "arg2"};
         MessageBundle mb = new MessageBundle("dummyId", arguments);
@@ -69,4 +93,33 @@
         assertEquals("Default not used", getFormattedMockString("dummyId", MessageBundle.TITLE, arguments, Locale.US),
                 mb.getTitle(Locale.US, "defaultText"));
     }
+
+    public void testWithProviderAndArguments() {
+        addMockProvider(); // Add wrong provider
+        String[] arguments = new String[]{"arg1", "arg2"};
+        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId", arguments);
+        try {
+            mb.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText arg1 arg2", mb.getText(Locale.US, "defaultText {0} {1}"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", MessageBundle.TEXT, arguments, Locale.US),
+                mb.getText(Locale.US));
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", MessageBundle.TITLE, arguments, Locale.US),
+                mb.getTitle(Locale.US));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", MessageBundle.TEXT, arguments, Locale.US),
+                mb.getText(Locale.US, "defaultText"));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", MessageBundle.TITLE, arguments, Locale.US),
+                mb.getTitle(Locale.US, "defaultText"));
+    }
 }
Index: src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
===================================================================
--- src/test/org/apache/commons/i18n/bundles/TextBundleTest.java	(revision 170884)
+++ src/test/org/apache/commons/i18n/bundles/TextBundleTest.java	(working copy)
@@ -43,6 +43,26 @@
                 textBundle.getText(Locale.US, "defaultText"));
     }
 
+    public void testWithProvider() {
+        addMockProvider(); // Add wrong provider
+        TextBundle textBundle = new TextBundle("dummyProvider", "dummyId");
+        try {
+            textBundle.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText", textBundle.getText(Locale.US, "defaultText"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use", getMockString("dummyProvider", "dummyId", TextBundle.TEXT, Locale.US),
+                textBundle.getText(Locale.US));
+        assertEquals("Default not used", getMockString("dummyProvider", "dummyId", TextBundle.TEXT, Locale.US),
+                textBundle.getText(Locale.US, "defaultText"));
+    }
+
     public void testWithArguments() {
         String[] arguments = new String[]{"arg1", "arg2"};
         TextBundle textBundle = new TextBundle("dummyId", arguments);
@@ -62,4 +82,26 @@
         assertEquals("Default not used", getFormattedMockString("dummyId", TextBundle.TEXT, arguments, Locale.US),
                 textBundle.getText(Locale.US, "defaultText"));
     }
-}
+
+    public void testWithProviderAndArguments() {
+        addMockProvider(); // Add wrong provider
+        String[] arguments = new String[]{"arg1", "arg2"};
+        TextBundle textBundle = new TextBundle("dummyProvider", "dummyId", arguments);
+        try {
+            textBundle.getText(Locale.US);
+            fail("Entry not found should cause error");
+        }
+        catch(MessageNotFoundException mnfex) {
+            assertEquals("Provider 'dummyProvider' not installed", mnfex.getMessage());
+        }
+        assertEquals("Default used", "defaultText arg1 arg2", textBundle.getText(Locale.US, "defaultText {0} {1}"));
+
+        addMockProvider("dummyProvider");
+
+        assertEquals("Normal use",
+                getFormattedMockString("dummyProvider", "dummyId", TextBundle.TEXT, arguments, Locale.US),
+                textBundle.getText(Locale.US));
+        assertEquals("Default not used",
+                getFormattedMockString("dummyProvider", "dummyId", TextBundle.TEXT, arguments, Locale.US),
+                textBundle.getText(Locale.US, "defaultText"));
+    }}
Index: src/java/org/apache/commons/i18n/MessageManager.java
===================================================================
--- src/java/org/apache/commons/i18n/MessageManager.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/MessageManager.java	(working copy)
@@ -74,6 +74,14 @@
     }
 
     /**
+     * Remove all <code>{@link MessageProvider}</code>s from the
+     * <code>MessageManager</code>. Used for tearing down unit tests.
+     */
+    static void clearMessageProviders() {
+        messageProviders.clear();
+    }
+
+    /**
      * Remove custom <code>{@link MessageProvider}</code> from the
      * <code>MessageManager</code>. Used for tearing down unit tests.
      *
@@ -82,6 +90,7 @@
     static void removeMessageProvider(String providerId) {
         messageProviders.remove(providerId);
     }
+
     /**
      * Iterates over all registered message providers in order to find the given
      * entry in the requested message bundle.
@@ -149,6 +158,64 @@
     }
 
     /**
+     * Tries to find the desired entry in the named message provider.
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param id
+     *            The identifier that will be used to retrieve the message
+     *            bundle
+     * @param entry
+     *            The desired message entry
+     * @param arguments
+     *            The dynamic parts of the message that will be evaluated using
+     *            the standard java text formatting abilities.
+     * @param locale
+     *            The locale in which the message will be printed
+     * @exception MessageNotFoundException
+     *                Will be thrown if the requested message provider cannot be found or
+     *                no message bundle can be found for the given id or if the desired
+     *                message entry is missing in the retrieved bundle
+     * @return The localized text
+     */
+    public static String getText(String providerId, String id, String entry, Object[] arguments,
+            Locale locale) throws MessageNotFoundException {
+        MessageProvider provider = (MessageProvider) messageProviders.get(providerId);
+        if(provider == null)
+            throw new MessageNotFoundException("Provider '" + providerId + "' not installed");
+        String text = provider.getText(id, entry, locale);
+        return MessageFormat.format(text, arguments);
+    }
+
+    /**
+     * Iterates over all registered message providers in order to find the given
+     * entry in the requested message bundle.
+     *
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param id
+     *            The identifier that will be used to retrieve the message
+     *            bundle
+     * @param entry
+     *            The desired message entry
+     * @param arguments
+     *            The dynamic parts of the message that will be evaluated using
+     *            the standard java text formatting abilities.
+     * @param locale
+     *            The locale in which the message will be printed
+     * @param defaultText
+     *            If no message bundle or message entry could be found for the
+     *            specified parameters, the default text will be returned.
+     * @return The localized text or the default text if the message could not
+     *         be found
+     */
+    public static String getText(String providerId, String id, String entry, Object[] arguments,
+            Locale locale, String defaultText) {
+        try {
+            return getText(providerId, id, entry, arguments, locale);
+        } catch (MessageNotFoundException e) {
+            return MessageFormat.format(defaultText, arguments);
+        }
+    }
+
+    /**
      * Returns a map containing all available message entries for the given
      * locale. The map contains keys of type {@link String}containing the keys
      * of the available message entries and values of type {@link String}
@@ -168,4 +235,18 @@
         }
         throw exception;
     }
+
+  /**
+   * Returns a map containing all available message entries for the given
+   * locale. The map contains keys of type {@link String}containing the keys
+   * of the available message entries and values of type {@link String}
+   * containing the localized message entries.
+   */
+  public static Map getEntries(String providerId, String id, Locale locale)
+          throws MessageNotFoundException {
+      MessageProvider provider = (MessageProvider) messageProviders.get(providerId);
+      if(provider == null)
+          throw new MessageNotFoundException("Provider '" + providerId + "' not installed");
+      return provider.getEntries(id, locale);
+  }
 }
\ No newline at end of file
Index: src/java/org/apache/commons/i18n/LocalizedBundle.java
===================================================================
--- src/java/org/apache/commons/i18n/LocalizedBundle.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/LocalizedBundle.java	(working copy)
@@ -42,16 +42,25 @@
 public class LocalizedBundle implements Serializable {
     public final static String ID = "id";
 
+    protected String providerId;
     protected String id;
     protected Object[] arguments;
 
+  /**
+   * @param providerId The name of the message provider (i.e. source) to use for the message
+   * @param messageId The messageId refers the corresponding bundle in the file containing
+   * the localized messages.
+   */
+  public LocalizedBundle(String providerId, String messageId) {
+      this(providerId, messageId, new Object[0]);
+  }
+
     /**
      * @param messageId The messageId refers the corresponding bundle in the file containing
      * the localized messages.
      */
     public LocalizedBundle(String messageId) {
-        this.id = messageId;
-        this.arguments = new Object[0];
+        this(messageId, new Object[0]);
     }
 
     /**
@@ -65,6 +74,19 @@
         this.arguments = arguments;
     }
 
+  /**
+   * @param providerId The name of the message provider (i.e. source) to use for the message
+   * @param messageId The messageId refers the corresponding bundle in the file containing
+   * the localized messages.
+   * @param arguments An array of objects containing arguments for the messages. These arguments
+   * are used to insert dynamic values into the localized messages.
+   */
+  public LocalizedBundle(String providerId, String messageId, Object[] arguments) {
+    this.providerId = providerId;
+    this.id = messageId;
+      this.arguments = arguments;
+  }
+
     /**
      * @return returns the id of this bundle
      */
@@ -78,8 +100,15 @@
     public Object[] getArguments() {
     	return arguments;
     }
-    
+
     /**
+     * @return The name of the message provider (i.e. source) to use for the message  
+     */
+    public String getProviderId() {
+        return providerId;
+    }
+
+    /**
      * @param key the key of the specific message entry in the message bundle
      * @param locale the locale for that this message should be rendered
      * @return returns the text of the desired message entry for the given locale  
@@ -87,7 +116,9 @@
      * in this bundle
      */
     public String getEntry(String key, Locale locale) throws MessageNotFoundException {
-        return MessageManager.getText(id, key, arguments, locale);
+        return providerId != null ?
+            MessageManager.getText(providerId, id, key, arguments, locale) :
+            MessageManager.getText(id, key, arguments, locale);
     }
 
     /**
@@ -97,6 +128,8 @@
      * @return returns the text of the desired message entry for the given locale  
      */
     public String getEntry(String key, Locale locale, String defaultText) {
-        return MessageManager.getText(id, key, arguments, locale, defaultText);
+        return providerId != null ?
+            MessageManager.getText(providerId, id, key, arguments, locale, defaultText) :
+            MessageManager.getText(id, key, arguments, locale, defaultText);
     }
 }
\ No newline at end of file
Index: src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
===================================================================
--- src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java	(working copy)
@@ -47,12 +47,9 @@
      * @see org.apache.commons.i18n.MessageProvider#getText(java.lang.String, java.lang.String, java.util.Locale)
      */
     public String getText(String id, String entry, Locale locale) throws MessageNotFoundException {
-        // TODO: Revise try/catch
         try {
             ResourceBundle resourceBundle = ResourceBundle.getBundle(baseName, locale);
-             return resourceBundle.getString(id+"."+entry);
-        } catch ( ClassCastException e ) {
-            // ignore all entries that are not of type String
+             return resourceBundle.getObject(id+"."+entry).toString();
         }
         catch ( MissingResourceException e ) {
             logger.log(
Index: src/java/org/apache/commons/i18n/bundles/ErrorBundle.java
===================================================================
--- src/java/org/apache/commons/i18n/bundles/ErrorBundle.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/bundles/ErrorBundle.java	(working copy)
@@ -45,6 +45,14 @@
     }
 
     /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     */
+    public ErrorBundle(String providerId, String messageId) {
+        super(providerId, messageId);
+    }
+
+    /**
      * @param messageId Unique message id that identifies the message 
      * @param arguments An array of objects conaining the values that should be
      * inserted into the localized message.  
@@ -54,6 +62,16 @@
     }
 
     /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     * @param arguments An array of objects conaining the values that should be
+     * inserted into the localized message.
+     */
+    public ErrorBundle(String providerId, String messageId, Object[] arguments) {
+        super(providerId, messageId, arguments);
+    }
+
+    /**
      * @param locale The locale that is used to find the appropriate localized text 
      * @return returns the localized message entry with the key <code>summary</code>
      * @throws MessageNotFoundException is thrown if no entry with key <code>summary</code> could be found in the message bundle identified by the given message identifier
Index: src/java/org/apache/commons/i18n/bundles/TextBundle.java
===================================================================
--- src/java/org/apache/commons/i18n/bundles/TextBundle.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/bundles/TextBundle.java	(working copy)
@@ -44,6 +44,14 @@
     }
 
     /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     */
+    public TextBundle(String providerId, String messageId) {
+        super(providerId, messageId);
+    }
+
+    /**
      * @param messageId Unique message id that identifies the message 
      * @param arguments An array of objects conaining the values that should be
      * inserted into the localized message.  
@@ -53,6 +61,16 @@
     }
 
     /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     * @param arguments An array of objects conaining the values that should be
+     * inserted into the localized message.
+     */
+    public TextBundle(String providerId, String messageId, Object[] arguments) {
+        super(providerId, messageId, arguments);
+    }
+
+    /**
      * @param locale The locale that is used to find the appropriate localized text 
      * @return returns the localized message entry with the key <code>text</code>
      * @throws MessageNotFoundException is thrown if no entry with key <code>text</code> could be found in the message bundle identified by the given message identifier
Index: src/java/org/apache/commons/i18n/bundles/MessageBundle.java
===================================================================
--- src/java/org/apache/commons/i18n/bundles/MessageBundle.java	(revision 170884)
+++ src/java/org/apache/commons/i18n/bundles/MessageBundle.java	(working copy)
@@ -42,6 +42,14 @@
     }
 
     /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     */
+    public MessageBundle(String providerId, String messageId) {
+        super(providerId, messageId);
+    }
+
+    /**
      * @param messageId Unique message id that identifies the message 
      * @param arguments An array of objects conaining the values that should be
      * inserted into the localized message.  
@@ -50,6 +58,15 @@
         super(messageId, arguments);
     }
 
+    /**
+     * @param providerId The name of the message provider (i.e. source) to use for the message
+     * @param messageId Unique message id that identifies the message
+     * @param arguments An array of objects conaining the values that should be
+     * inserted into the localized message.
+     */
+    public MessageBundle(String providerId, String messageId, Object[] arguments) {
+        super(providerId, messageId, arguments);
+    }
 
     /**
      * @param locale The locale that is used to find the appropriate localized text 


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[i18n] Basic architecture/component usage

Posted by Mattias J <ma...@expertsystem.se>.
[was "Re: [i18n PATCH] Adding provider qualifying"]

At 2005-05-19 16:41, you wrote:
>But, to be honest, I'm a bit disappointed at how this project is being 
>developed.  I feel that i18n would benefit tremendously by reusing instead 
>of reinventing.

Since Commons Resources and i18n seems to basically solve the same problem, 
my very first post to this list a month ago included the question whether 
i18n and Resources were going to continue to co-exist, and what was the 
relationship between them. After getting the impression they would continue 
to co-exist i18n was the natural choice because of our prerequisites.

In our project we store the language specific texts in a database. Among 
60+ tables there are a few that contain several columns to provide - for 
example - text, abbreviated text and detailed description for a single ID + 
language/locale entry. So supporting multiple texts per ID is a basic 
requirement for us.

>As was pointed out months ago, there's just too much you get for free by 
>leveraging other components and communities.
>
>With all do respect to those of you working on i18n, I'm not currently 
>using this component in my own work, but I plan to in the near future.  At 
>that time I'll most likely fork the code, strip out the bottom half 
>(dealing with message retrieval) and plug in commons-resources.

To be honest I haven't really considered building i18n *on top of* 
commons-resources before. But - even though I have not studied the 
Resources API in details - I must disapprove since I do not see an 
obvious/useful way to handle the above scenario using Resources.
For this to be supported by Resources in a useful manner, Resources needs 
to be extended. And if Resources is extended in such a way, we might just 
as well move what is left in i18n into the Resources component as well.

>I have no interest in trying to redo my work from Commons Resources or 
>reimplement the 3 Database-based impls of such.
>
>And what about the hundreds of JUnit tests. One thing I've been working on 
>lately is getting Resources to 100% test coverage.  I would hate to ask 
>someone to redo their work because I "didn't want to depend on another 
>project".

Another idea would be to add a CommonsResourcesProvider wich you could opt 
to use with i18n.

FYI, I have assured i18n has 100% test coverage.
The coverage report is not currently included in the build, but if somebody 
would add emma.jar and emma_ant.jar to the lib dir, I could provide an 
updated build.xml.

  /Mattias Jiderhamn 


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


AW: [i18n PATCH] Adding provider qualifying

Posted by Daniel Florey <da...@web.de>.
It should be no problem to plug in a CommonsResourceMessageProvider as
Mattias pointed out.
In case of i18n the benefits from using other components would be not that
much as this component is really small and simple. The disadvantages when
relying on other libraries in daily use (version conflicts in bigger
projects) justify that we decided not to use them.
If you ever worked on larger commercial java based projects using
proprietary software, you probably know what I mean.
As long as the java language is not supporting different versions of the
same component at the same time (without using different classloaders and
all of this mess as no average developer will manage to do so) this is no
way to go.
Have a look at my thread regarding this topic:
http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200412.mbox/%3c
E1CexAc-0005nu-00@smtp05.web.de%3e

Cheers,
Daniel

> -----Ursprüngliche Nachricht-----
> Von: commons-dev-return-71431-daniel.florey=web.de@jakarta.apache.org
> [mailto:commons-dev-return-71431-daniel.florey=web.de@jakarta.apache.org]
> Im Auftrag von James Mitchell
> Gesendet: Donnerstag, 19. Mai 2005 16:42
> An: Jakarta Commons Developers List
> Betreff: Re: [i18n PATCH] Adding provider qualifying
> 
> I'm happy to help.
> 
> But, to be honest, I'm a bit disappointed at how this project is being
> developed.  I feel that i18n would benefit tremendously by reusing instead
> of reinventing.  As was pointed out months ago, there's just too much you
> get for free by leveraging other components and communities.
> 
> With all do respect to those of you working on i18n, I'm not currently
> using
> this component in my own work, but I plan to in the near future.  At that
> time I'll most likely fork the code, strip out the bottom half (dealing
> with
> message retrieval) and plug in commons-resources.  I have no interest in
> trying to redo my work from Commons Resources or reimplement the 3
> Database-based impls of such.  And what about the hundreds of JUnit tests.
> One thing I've been working on lately is getting Resources to 100% test
> coverage.  I would hate to ask someone to redo their work because I
> "didn't
> want to depend on another project".
> 
> Thanks.
> 
> --
> James Mitchell
> Software Engineer / Open Source Evangelist
> Consulting / Mentoring / Freelance
> EdgeTech, Inc.
> http://www.edgetechservices.net/
> 678.910.8017
> AIM:   jmitchtx
> Yahoo: jmitchtx
> MSN:   jmitchell@apache.org
> 
> 
> 
> 
> ----- Original Message -----
> From: "Mattias J" <ma...@expertsystem.se>
> To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>;
> "Daniel Florey" <da...@web.de>
> Sent: Thursday, May 19, 2005 3:13 AM
> Subject: [i18n PATCH] Adding provider qualifying
> 
> 
> >I have previously discussed with Daniel Florey a change that allows the
> >user to qualify the provider (or source or namespace) to be used for a
> >given text entry. My main motivation for this is to allow the same entry
> >key in several different text sources, but this also provides better
> >performance since the API does not have to loop over the different
> >providers in search for the given entry.
> >
> > Thanks to James Mitchell I am now able to create the diff for this
> change;
> > see below. I would be happy if Daniel or anybody else would review and
> > commit this patch.
> >
> > Included in the patch is also a minor change that allows non-string
> > ResourceBundle entries to be used (via toString()).
> >
> > After this there are a few more changes I would like to discuss -
> > conserning class and package dependencies among others - so Daniel,
> please
> > tell me when you are available again. I also hope to find the time to
> > create an example DatabaseProvider.
> >
> > Now here is the diff.
> > (Again, if lines are wrapped in the e-mail, I can provide the diff by
> > personal e-mail or in a bugzilla entry).
> >
> > Index: src/test/org/apache/commons/i18n/MockProviderTestBase.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/MockProviderTestBase.java (revision
> > 170884)
> > +++ src/test/org/apache/commons/i18n/MockProviderTestBase.java (working
> > copy)
> > @@ -30,36 +30,41 @@
> >  * @author Mattias Jiderhamn
> >  */
> > public abstract class MockProviderTestBase extends TestCase {
> > -    /**
> > -     * Mock message provider that returns a string made up of the
> > arguments passed to it.
> > -     */
> > -    final private MessageProvider mockMessageProvider = new
> > MessageProvider() {
> > -        public String getText(String id, String entry, Locale locale)
> > throws MessageNotFoundException {
> > -            return MockProviderTestBase.getMockString(id, entry,
> locale);
> > -        }
> >
> > -        public Map getEntries(String id, Locale locale) throws
> > MessageNotFoundException {
> > -            Map output = new HashMap();
> > -            output.put("entry1",
> > MockProviderTestBase.getMockString(id,"entry1",locale));
> > -            output.put("entry2",
> > MockProviderTestBase.getMockString(id,"entry2",locale));
> > -            return output;
> > -        }
> > -    };
> > -
> >     public void tearDown() {
> >         /* Remove mock provider after each test, to allow for
> > MessageNotFoundExceptions */
> > -        MessageManager.removeMessageProvider("mock");
> > -        removeThrowingMockProvider();
> > +        MessageManager.clearMessageProviders();
> >     }
> >
> >     /**
> >      * Add mock provider to <code>MessageManager</code>.
> >      */
> >     protected void addMockProvider() {
> > -        MessageManager.addMessageProvider("mock", mockMessageProvider);
> > +        addMockProvider("mock");
> >     }
> >
> >     /**
> > +     * Add mock provider to <code>MessageManager</code>.
> > +     */
> > +    protected void addMockProvider(final String providerId) {
> > +         //  Mock message provider that returns a string made up of the
> > arguments passed to it.
> > +        MessageProvider mockMessageProvider = new MessageProvider() {
> > +            public String getText(String id, String entry, Locale
> locale)
> > throws MessageNotFoundException {
> > +                return MockProviderTestBase.getMockString(providerId,
> id,
> > entry, locale);
> > +            }
> > +
> > +            public Map getEntries(String id, Locale locale) throws
> > MessageNotFoundException {
> > +                Map output = new HashMap();
> > +                output.put("entry1",
> > MockProviderTestBase.getMockString(providerId,id,"entry1",locale));
> > +                output.put("entry2",
> > MockProviderTestBase.getMockString(providerId,id,"entry2",locale));
> > +                return output;
> > +            }
> > +        };
> > +
> > +        MessageManager.addMessageProvider(providerId,
> > mockMessageProvider);
> > +    }
> > +
> > +    /**
> >      * Add provider that always throws error to
> > <code>MessageManager</code>.
> >      */
> >     protected void addThrowingMockProvider() {
> > @@ -82,10 +87,19 @@
> >     // Utility methods
> >
> > ////////////////////////////////////////////////////////////////////////
> >
> > +    public static String getMockString(String providerId, String id,
> > String entry, Locale locale) throws MessageNotFoundException {
> > +        return ((providerId != null) ? "Source=" + providerId + " " :
> "")
> > +
> > +                "Id=" + id + " Entry=" + entry + " Locale=" + locale +
> > "";
> > +    }
> > +
> >     public static String getMockString(String id, String entry, Locale
> > locale) throws MessageNotFoundException {
> > -        return "Id=" + id + " Entry=" + entry + " Locale=" + locale +
> "";
> > +        return getMockString("mock", id, entry, locale);
> >     }
> >
> > +    public static String getFormattedMockString(String providerId,
> String
> > id, String entry, String[] arguments, Locale locale) {
> > +        return MessageFormat.format(getMockString(providerId, id,
> entry,
> > locale), arguments);
> > +    }
> > +
> >     public static String getFormattedMockString(String id, String entry,
> > String[] arguments, Locale locale) {
> >         return MessageFormat.format(getMockString(id, entry, locale),
> > arguments);
> >     }
> > Index: src/test/org/apache/commons/i18n/MessageManagerTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/MessageManagerTest.java (revision
> > 170884)
> > +++ src/test/org/apache/commons/i18n/MessageManagerTest.java (working
> > copy)
> > @@ -55,26 +55,48 @@
> >
> >         addMockProvider(); // Add mock provider
> >
> > -        assertEquals("Throwing mock not used", "Id=dummyId
> > Entry=dummyEntry Locale=en_US",
> > +        assertEquals("Throwing mock not used", "Source=mock Id=dummyId
> > Entry=dummyEntry Locale=en_US",
> >                 MessageManager.getText("dummyId", "dummyEntry", null,
> > Locale.US, "defaultText"));
> >
> >         removeThrowingMockProvider(); // Removing throwing mock and keep
> > only normal mock
> >
> > -        assertEquals("Default text not used", "Id=dummyId
> > Entry=dummyEntry Locale=en_US",
> > +        assertEquals("Default text not used", "Source=mock Id=dummyId
> > Entry=dummyEntry Locale=en_US",
> >                 MessageManager.getText("dummyId", "dummyEntry", null,
> > Locale.US, "defaultText"));
> >
> > -        assertEquals("Normal lookup", "Id=id Entry=entry Locale=en_US",
> > +        assertEquals("Normal lookup", "Source=mock Id=id Entry=entry
> > Locale=en_US",
> >                 MessageManager.getText("id", "entry", null, Locale.US));
> >         assertEquals("Single argument",
> > -                "Id=id Entry=entry value1 Locale=en_US",
> > +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
> >                 MessageManager.getText("id", "entry {0}", new String[]
> > {"value1"}, Locale.US));
> >         assertEquals("Multiple arguments",
> > -                "Id=id Entry=entry value0: value1 Locale=en_US",
> > +                "Source=mock Id=id Entry=entry value0: value1
> > Locale=en_US",
> >                 MessageManager.getText("id", "entry {0}: {1}", new
> > String[] {"value0", "value1"},Locale.US));
> >
> >         assertEquals("Single argument and default",
> > -                "Id=id Entry=entry value1 Locale=en_US",
> > +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
> >                 MessageManager.getText("id", "entry {0}", new String[]
> > {"value1"},Locale.US, "defaultText"));
> > +
> > +        // Named provider not found
> > +        try {
> > +            MessageManager.getText("mockProvider2", "dummyId",
> > "dummyEntry", null, Locale.US);
> > +            fail("Unknown provider should throw Exception");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Error text", "Provider 'mockProvider2' not
> > installed", mnfex.getMessage());
> > +        }
> > +
> > +        assertEquals("Default text used", "defaultText",
> > +                MessageManager.getText("mockProvider2", "dummyId",
> > "dummyEntry", null, Locale.US, "defaultText"));
> > +
> > +
> > +        // Named provider found
> > +        addMockProvider("mockProvider2");
> > +
> > +        assertEquals("Default text not used, qualified lookup",
> > "Source=mockProvider2 Id=dummyId Entry=dummyEntry Locale=en_US",
> > +                MessageManager.getText("mockProvider2", "dummyId",
> > "dummyEntry", null, Locale.US, "defaultText"));
> > +
> > +        assertEquals("Normal qualified lookup", "Source=mockProvider2
> > Id=id Entry=entry Locale=en_US",
> > +                MessageManager.getText("mockProvider2", "id", "entry",
> > null, Locale.US));
> >     }
> >
> >     public void testGetEntries() {
> > @@ -100,8 +122,8 @@
> >
> >         Map entries = MessageManager.getEntries("dummyId", Locale.US);
> >         assertEquals("No of entries", 2, entries.size());
> > -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1
> > Locale=en_US", entries.get("entry1"));
> > -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2
> > Locale=en_US", entries.get("entry2"));
> > +        assertEquals("Entry 1 match", "Source=mock Id=dummyId
> > Entry=entry1 Locale=en_US", entries.get("entry1"));
> > +        assertEquals("Entry 2 match", "Source=mock Id=dummyId
> > Entry=entry2 Locale=en_US", entries.get("entry2"));
> >
> >         removeThrowingMockProvider(); // Removing throwing mock and keep
> > only normal mock
> >
> > @@ -109,7 +131,24 @@
> >
> >         entries = MessageManager.getEntries("dummyId", Locale.US);
> >         assertEquals("No of entries", 2, entries.size());
> > -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1
> > Locale=en_US", entries.get("entry1"));
> > -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2
> > Locale=en_US", entries.get("entry2"));
> > +        assertEquals("Entry 1 match", "Source=mock Id=dummyId
> > Entry=entry1 Locale=en_US", entries.get("entry1"));
> > +        assertEquals("Entry 2 match", "Source=mock Id=dummyId
> > Entry=entry2 Locale=en_US", entries.get("entry2"));
> > +
> > +        // Named provider not found
> > +        try {
> > +            MessageManager.getEntries("mockProvider2", "dummyId",
> > Locale.US);
> > +            fail("Unknown provider should throw Exception");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Error text", "Provider 'mockProvider2' not
> > installed", mnfex.getMessage());
> > +        }
> > +
> > +        // Named provider found
> > +        addMockProvider("mockProvider2");
> > +
> > +        entries = MessageManager.getEntries("mockProvider2", "dummyId",
> > Locale.US);
> > +        assertEquals("No of entries", 2, entries.size());
> > +        assertEquals("Entry 1 match", "Source=mockProvider2 Id=dummyId
> > Entry=entry1 Locale=en_US", entries.get("entry1"));
> > +        assertEquals("Entry 2 match", "Source=mockProvider2 Id=dummyId
> > Entry=entry2 Locale=en_US", entries.get("entry2"));
> >     }
> > }
> > \ No newline at end of file
> > Index: src/test/org/apache/commons/i18n/LocalizedBundleTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/LocalizedBundleTest.java (revision
> > 170884)
> > +++ src/test/org/apache/commons/i18n/LocalizedBundleTest.java (working
> > copy)
> > @@ -24,21 +24,38 @@
> > public class LocalizedBundleTest extends MockProviderTestBase {
> >     public void testConstructors() {
> >         LocalizedBundle lb = new LocalizedBundle("dummyId1");
> > +        assertNull("No provider", lb.getProviderId());
> >         assertEquals("Id set", "dummyId1", lb.getId());
> >         assertNotNull("Arguments not null", lb.getArguments());
> >         assertEquals("No arguments", 0, lb.getArguments().length);
> >
> > +        LocalizedBundle lbProvider = new
> > LocalizedBundle("dummyProvider2", "dummyId2");
> > +        assertEquals("Provider set", "dummyProvider2",
> > lbProvider.getProviderId());
> > +        assertEquals("Id set", "dummyId2", lbProvider.getId());
> > +        assertNotNull("Arguments not null", lbProvider.getArguments());
> > +        assertEquals("No arguments", 0,
> > lbProvider.getArguments().length);
> > +
> >         String[] arguments = new String[]{"arg1", "arg2"};
> > -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2",
> > arguments);
> > -        assertEquals("Id set", "dummyId2", lbArgs.getId());
> > +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3",
> > arguments);
> > +        assertNull("No provider", lbArgs.getProviderId());
> > +        assertEquals("Id set", "dummyId3", lbArgs.getId());
> >         assertNotNull("Arguments not null", lbArgs.getArguments());
> >         assertEquals("No of arguments", 2,
> lbArgs.getArguments().length);
> >         assertEquals("Arguments", arguments, lbArgs.getArguments());
> > +
> > +        LocalizedBundle lbProviderArgs = new
> > LocalizedBundle("dummyProvider4", "dummyId4", arguments);
> > +        assertEquals("Provider set", "dummyProvider4",
> > lbProviderArgs.getProviderId());
> > +        assertEquals("Id set", "dummyId4", lbProviderArgs.getId());
> > +        assertNotNull("Arguments not null",
> > lbProviderArgs.getArguments());
> > +        assertEquals("No of arguments", 2,
> > lbProviderArgs.getArguments().length);
> > +        assertEquals("Arguments", arguments,
> > lbProviderArgs.getArguments());
> >     }
> >
> >     public void testGetEntry() {
> >         LocalizedBundle lb = new LocalizedBundle("dummyId1");
> > -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", new
> > String[] {"arg1", "arg2"});
> > +        LocalizedBundle lbProvider = new
> > LocalizedBundle("dummyProvider2", "dummyId2");
> > +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", new
> > String[] {"arg1", "arg2"});
> > +        LocalizedBundle lbProviderArgs = new
> > LocalizedBundle("dummyProvider4", "dummyId4", new String[] {"arg1",
> > "arg2"});
> >
> >         // Test errors
> >         try {
> > @@ -63,15 +80,53 @@
> >
> >         addMockProvider(); // Add mock provider
> >
> > -        assertEquals("Default text not used", "Id=dummyId1
> > Entry=dummyEntry Locale=en_US",
> > +        assertEquals("Default text not used", getMockString("dummyId1",
> > "dummyEntry", Locale.US),
> >                 lb.getEntry("dummyEntry", Locale.US, "defaltText"));
> >
> > -        assertEquals("Normal lookup", "Id=dummyId1 Entry=entry
> > Locale=en_US", lb.getEntry("entry", Locale.US));
> > -        assertEquals("Arguments missing", "Id=dummyId1 Entry=entry {0}
> > Locale=en_US",
> > +        assertEquals("Normal lookup", getMockString("dummyId1",
> "entry",
> > Locale.US), lb.getEntry("entry", Locale.US));
> > +        assertEquals("Arguments missing", "Source=mock Id=dummyId1
> > Entry=entry {0} Locale=en_US",
> >                 lb.getEntry("entry {0}", Locale.US));
> > -        assertEquals("Argument", "Id=dummyId2 Entry=entry arg1 arg2
> > Locale=en_US",
> > +        assertEquals("Argument", "Source=mock Id=dummyId3 Entry=entry
> > arg1 arg2 Locale=en_US",
> >                 lbArgs.getEntry("entry {0} {1}", Locale.US));
> > -        assertEquals("Arguments and default", "Id=dummyId2 Entry=entry
> > arg1 arg2 Locale=en_US",
> > +        assertEquals("Arguments and default", "Source=mock Id=dummyId3
> > Entry=entry arg1 arg2 Locale=en_US",
> >                 lbArgs.getEntry("entry {0} {1}", Locale.US,
> > "defaultText"));
> > +
> > +        // Named provider not found
> > +        try {
> > +            lbProvider.getEntry("dummyEntry", Locale.US);
> > +            fail("Unknown provider should throw Exception");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Error text", "Provider 'dummyProvider2' not
> > installed", mnfex.getMessage());
> > +        }
> > +
> > +        try {
> > +            lbProviderArgs.getEntry("dummyEntry", Locale.US);
> > +            fail("Unknown provider should throw Exception");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Error text", "Provider 'dummyProvider4' not
> > installed", mnfex.getMessage());
> > +        }
> > +
> > +        assertEquals("Default text", "defaultText",
> > lbProvider.getEntry("dummyEntry", Locale.US, "defaultText"));
> > +        assertEquals("Default text", "defaultText",
> > lbProviderArgs.getEntry("dummyEntry", Locale.US, "defaultText"));
> > +
> > +        // Named provider found
> > +        addMockProvider("dummyProvider2");
> > +        addMockProvider("dummyProvider4");
> > +
> > +        assertEquals("Named provider: Default text not used",
> > +                getMockString("dummyProvider2", "dummyId2",
> "dummyEntry",
> > Locale.US),
> > +                lbProvider.getEntry("dummyEntry", Locale.US,
> > "defaltText"));
> > +
> > +        assertEquals("Named provider: Normal lookup",
> > getMockString("dummyProvider2", "dummyId2", "entry", Locale.US),
> > +                lbProvider.getEntry("entry", Locale.US));
> > +        assertEquals("Named provider: Arguments missing",
> > "Source=dummyProvider2 Id=dummyId2 Entry=entry {0} Locale=en_US",
> > +                lbProvider.getEntry("entry {0}", Locale.US));
> > +        assertEquals("Named provider: Argument", "Source=dummyProvider4
> > Id=dummyId4 Entry=entry arg1 arg2 Locale=en_US",
> > +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US));
> > +        assertEquals("Named provider: Arguments and default",
> > +                "Source=dummyProvider4 Id=dummyId4 Entry=entry arg1
> arg2
> > Locale=en_US",
> > +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US,
> > "defaultText"));
> >     }
> > }
> > Index: src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
> (revision
> > 170884)
> > +++ src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
> (working
> > copy)
> > @@ -2,7 +2,7 @@
> > *
> > * ====================================================================
> > *
> > -* Copyright 2004 The Apache Software Foundation
> > +* Copyright 2004 The Apache Software Foundation
> > *
> > * Licensed under the Apache License, Version 2.0 (the "License");
> > * you may not use this file except in compliance with the License.
> > @@ -56,12 +56,12 @@
> >         }
> >
> >         XMLMessageProvider.install("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> >
> >         assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
> >
> >         XMLMessageProvider.update("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> >
> >         assertEquals("OK after update", "Hallo Welt",
> > testMessage.getTitle(Locale.GERMAN));
> >
> > @@ -77,14 +77,14 @@
> >
> >         // Try to parse non-XML file
> >         XMLMessageProvider.install("org.apache.commons-i18n.error",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messag
> eBundle.properties"));
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messag
> eBundle.properties"));
> >     }
> > -
> > +
> >     public void testGetText() {
> > //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> > -//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> > +//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> >         XMLMessageProvider xmlmp = new
> > XMLMessageProvider("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> >
> >         assertEquals("Default locale", "hello world",
> > xmlmp.getText("helloWorld", "title", Locale.US));
> >         assertEquals("Default locale", "hello world",
> > xmlmp.getText("helloWorld", "title", Locale.UK));
> > @@ -123,9 +123,9 @@
> >
> >     public void testGetTextVariants() {
> > //        XMLMessageProvider.install("org.apache.commons-i18n.variants",
> > -//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> > +//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> >         XMLMessageProvider xmlmp = new
> > XMLMessageProvider("org.apache.commons-i18n.variants",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> >
> >         assertEquals("hello world", xmlmp.getText("variants", "theKey",
> > Locale.ENGLISH));
> >         assertEquals("Botswana", "Hello Botswana",
> > xmlmp.getText("variants", "theKey", new Locale("", "BW")));
> > @@ -135,9 +135,9 @@
> >
> >     public void testGetEntries() {
> > //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> > -//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> > +//
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> >         Map usEntries = new
> > XMLMessageProvider("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> >                     getEntries("helloWorld", Locale.US);
> >         assertEquals("Default locale, no of entries", 5,
> > usEntries.size());
> >         assertEquals("Default locale, titel", "hello world",
> > usEntries.get("title"));
> > @@ -151,7 +151,7 @@
> >         assertEquals("This entry is not translated to any other
> languages
> > (XML)", usEntries.get("notTranslated"));
> >
> >         Map germanEntries = new
> > XMLMessageProvider("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> >                     getEntries("helloWorld", Locale.GERMAN);
> >         assertEquals("No of entries", 4, germanEntries.size());
> >         assertEquals("Hallo Welt", germanEntries.get("title"));
> > @@ -163,7 +163,7 @@
> > //        assertEquals("This entry is not translated to any other
> > languages", germanEntries.get("notTranslated"));
> >
> >         Map japaneseEntries = new
> > XMLMessageProvider("org.apache.commons-i18n.test",
> > -
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> > +
> >
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> >                     getEntries("helloWorld", Locale.JAPANESE);
> >         assertEquals("Fallback locale, no of entries", 5,
> > japaneseEntries.size());
> >
> > Index:
> > src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> > ===================================================================
> > ---
> > src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> > (revision 170884)
> > +++
> > src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> > (working copy)
> > @@ -2,7 +2,7 @@
> > *
> > * ====================================================================
> > *
> > -* Copyright 2004 The Apache Software Foundation
> > +* Copyright 2004 The Apache Software Foundation
> > *
> > * Licensed under the Apache License, Version 2.0 (the "License");
> > * you may not use this file except in compliance with the License.
> > @@ -45,7 +45,7 @@
> >         ResourceBundleMessageProvider.uninstall("messageBundle");
> >         ResourceBundleMessageProvider.uninstall("messageBundle2");
> >         ResourceBundleMessageProvider.uninstall("nonExistentBundle");
> > -
> >
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListRes
> ourceBundle");
> > +
> >
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListRes
> ourceBundle");
> >     }
> >
> >     public void testInstallResourceBundle() {
> > @@ -89,17 +89,11 @@
> >
> >         // Test with list resource bundle
> > //        ResourceBundleMessageProvider.uninstall("messageBundle"); //
> > Remove
> > -//
> >
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResou
> rceBundle");
> > // Install ListResourceBundle
> > +//
> >
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResou
> rceBundle");
> > // Install ListResourceBundle
> >         ResourceBundleMessageProvider listResourceBundleProvider =
> >                 new
> >
> ResourceBundleMessageProvider("org.apache.commons.i18n.MyListResourceBundl
> e");
> > // Install ListResourceBundle
> >         assertEquals("Value from ListResourceBundle",
> "listResourceValue",
> > listResourceBundleProvider.getText("helloWorld", "title", Locale.US));
> > -        try {
> > -            String s = listResourceBundleProvider.getText("helloWorld",
> > "text", Locale.US);
> > -            fail("Entry should not be found, since it is numeric. Found
> > text: " + s);
> > -        }
> > -        catch(MessageNotFoundException mnfex) {
> > -            assertEquals("No message entries found for bundle with key
> > helloWorld", mnfex.getMessage());
> > -        }
> > +        assertEquals("Value from ListResourceBundle", "1",
> > listResourceBundleProvider.getText("helloWorld", "text", Locale.US));
> >
> >         try {
> >             rbmp.getText("nonExistentId", "nonExistentEntry",
> Locale.US);
> > Index: src/test/org/apache/commons/i18n/I18nTestSuite.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/I18nTestSuite.java (revision
> 170884)
> > +++ src/test/org/apache/commons/i18n/I18nTestSuite.java (working copy)
> > @@ -2,7 +2,7 @@
> > *
> > * ====================================================================
> > *
> > -* Copyright 2004 The Apache Software Foundation
> > +* Copyright 2004 The Apache Software Foundation
> > *
> > * Licensed under the Apache License, Version 2.0 (the "License");
> > * you may not use this file except in compliance with the License.
> > Index: src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> > (revision 170884)
> > +++ src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> (working
> > copy)
> > @@ -52,6 +52,38 @@
> >                 eb.getDetails(Locale.US, "defaultText"));
> >     }
> >
> > +    public void testWithProvider() {
> > +        addMockProvider(); // Add wrong provider
> > +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId");
> > +        try {
> > +            eb.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText",
> eb.getText(Locale.US,
> > "defaultText"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.TEXT, Locale.US),
> > +                eb.getText(Locale.US));
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.TITLE, Locale.US),
> > +                eb.getTitle(Locale.US));
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.SUMMARY, Locale.US),
> > +                eb.getSummary(Locale.US));
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.DETAILS, Locale.US),
> > +                eb.getDetails(Locale.US));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.TEXT, Locale.US),
> > +                eb.getText(Locale.US, "defaultText"));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.TITLE, Locale.US),
> > +                eb.getTitle(Locale.US, "defaultText"));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.SUMMARY, Locale.US),
> > +                eb.getSummary(Locale.US, "defaultText"));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", ErrorBundle.DETAILS, Locale.US),
> > +                eb.getDetails(Locale.US, "defaultText"));
> > +    }
> > +
> >     public void testWithArguments() {
> >         String[] arguments = new String[]{"arg1", "arg2"};
> >         ErrorBundle eb = new ErrorBundle("dummyId", arguments);
> > @@ -83,4 +115,45 @@
> >         assertEquals("Default not used",
> getFormattedMockString("dummyId",
> > ErrorBundle.DETAILS, arguments, Locale.US),
> >                 eb.getDetails(Locale.US, "defaultText"));
> >     }
> > +
> > +    public void testWithProviderAndArguments() {
> > +        addMockProvider(); // Add wrong provider
> > +        String[] arguments = new String[]{"arg1", "arg2"};
> > +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId",
> > arguments);
> > +        try {
> > +            eb.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText arg1 arg2",
> > eb.getText(Locale.US, "defaultText {0} {1}"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.TEXT, arguments, Locale.US),
> > +                eb.getText(Locale.US));
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.TITLE, arguments, Locale.US),
> > +                eb.getTitle(Locale.US));
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.SUMMARY, arguments, Locale.US),
> > +                eb.getSummary(Locale.US));
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.DETAILS, arguments, Locale.US),
> > +                eb.getDetails(Locale.US));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.TEXT, arguments, Locale.US),
> > +                eb.getText(Locale.US, "defaultText"));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.TITLE, arguments, Locale.US),
> > +                eb.getTitle(Locale.US, "defaultText"));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.SUMMARY, arguments, Locale.US),
> > +                eb.getSummary(Locale.US, "defaultText"));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > ErrorBundle.DETAILS, arguments, Locale.US),
> > +                eb.getDetails(Locale.US, "defaultText"));
> > +    }
> > }
> > \ No newline at end of file
> > Index: src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> > (revision 170884)
> > +++ src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> > (working copy)
> > @@ -46,6 +46,30 @@
> >                 mb.getTitle(Locale.US, "defaultText"));
> >     }
> >
> > +    public void testWithProvider() {
> > +        addMockProvider(); // Add wrong provider
> > +        MessageBundle mb = new MessageBundle("dummyProvider",
> "dummyId");
> > +        try {
> > +            mb.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText",
> mb.getText(Locale.US,
> > "defaultText"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", MessageBundle.TEXT, Locale.US),
> > +                mb.getText(Locale.US));
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", MessageBundle.TITLE, Locale.US),
> > +                mb.getTitle(Locale.US));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", MessageBundle.TEXT, Locale.US),
> > +                mb.getText(Locale.US, "defaultText"));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", MessageBundle.TITLE, Locale.US),
> > +                mb.getTitle(Locale.US, "defaultText"));
> > +    }
> > +
> >     public void testWithArguments() {
> >         String[] arguments = new String[]{"arg1", "arg2"};
> >         MessageBundle mb = new MessageBundle("dummyId", arguments);
> > @@ -69,4 +93,33 @@
> >         assertEquals("Default not used",
> getFormattedMockString("dummyId",
> > MessageBundle.TITLE, arguments, Locale.US),
> >                 mb.getTitle(Locale.US, "defaultText"));
> >     }
> > +
> > +    public void testWithProviderAndArguments() {
> > +        addMockProvider(); // Add wrong provider
> > +        String[] arguments = new String[]{"arg1", "arg2"};
> > +        MessageBundle mb = new MessageBundle("dummyProvider",
> "dummyId",
> > arguments);
> > +        try {
> > +            mb.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText arg1 arg2",
> > mb.getText(Locale.US, "defaultText {0} {1}"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > MessageBundle.TEXT, arguments, Locale.US),
> > +                mb.getText(Locale.US));
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > MessageBundle.TITLE, arguments, Locale.US),
> > +                mb.getTitle(Locale.US));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > MessageBundle.TEXT, arguments, Locale.US),
> > +                mb.getText(Locale.US, "defaultText"));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > MessageBundle.TITLE, arguments, Locale.US),
> > +                mb.getTitle(Locale.US, "defaultText"));
> > +    }
> > }
> > Index: src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
> > ===================================================================
> > --- src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
> (revision
> > 170884)
> > +++ src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
> (working
> > copy)
> > @@ -43,6 +43,26 @@
> >                 textBundle.getText(Locale.US, "defaultText"));
> >     }
> >
> > +    public void testWithProvider() {
> > +        addMockProvider(); // Add wrong provider
> > +        TextBundle textBundle = new TextBundle("dummyProvider",
> > "dummyId");
> > +        try {
> > +            textBundle.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText",
> > textBundle.getText(Locale.US, "defaultText"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use", getMockString("dummyProvider",
> > "dummyId", TextBundle.TEXT, Locale.US),
> > +                textBundle.getText(Locale.US));
> > +        assertEquals("Default not used", getMockString("dummyProvider",
> > "dummyId", TextBundle.TEXT, Locale.US),
> > +                textBundle.getText(Locale.US, "defaultText"));
> > +    }
> > +
> >     public void testWithArguments() {
> >         String[] arguments = new String[]{"arg1", "arg2"};
> >         TextBundle textBundle = new TextBundle("dummyId", arguments);
> > @@ -62,4 +82,26 @@
> >         assertEquals("Default not used",
> getFormattedMockString("dummyId",
> > TextBundle.TEXT, arguments, Locale.US),
> >                 textBundle.getText(Locale.US, "defaultText"));
> >     }
> > -}
> > +
> > +    public void testWithProviderAndArguments() {
> > +        addMockProvider(); // Add wrong provider
> > +        String[] arguments = new String[]{"arg1", "arg2"};
> > +        TextBundle textBundle = new TextBundle("dummyProvider",
> > "dummyId", arguments);
> > +        try {
> > +            textBundle.getText(Locale.US);
> > +            fail("Entry not found should cause error");
> > +        }
> > +        catch(MessageNotFoundException mnfex) {
> > +            assertEquals("Provider 'dummyProvider' not installed",
> > mnfex.getMessage());
> > +        }
> > +        assertEquals("Default used", "defaultText arg1 arg2",
> > textBundle.getText(Locale.US, "defaultText {0} {1}"));
> > +
> > +        addMockProvider("dummyProvider");
> > +
> > +        assertEquals("Normal use",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > TextBundle.TEXT, arguments, Locale.US),
> > +                textBundle.getText(Locale.US));
> > +        assertEquals("Default not used",
> > +                getFormattedMockString("dummyProvider", "dummyId",
> > TextBundle.TEXT, arguments, Locale.US),
> > +                textBundle.getText(Locale.US, "defaultText"));
> > +    }}
> > Index: src/java/org/apache/commons/i18n/MessageManager.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/MessageManager.java (revision
> 170884)
> > +++ src/java/org/apache/commons/i18n/MessageManager.java (working copy)
> > @@ -74,6 +74,14 @@
> >     }
> >
> >     /**
> > +     * Remove all <code>{@link MessageProvider}</code>s from the
> > +     * <code>MessageManager</code>. Used for tearing down unit tests.
> > +     */
> > +    static void clearMessageProviders() {
> > +        messageProviders.clear();
> > +    }
> > +
> > +    /**
> >      * Remove custom <code>{@link MessageProvider}</code> from the
> >      * <code>MessageManager</code>. Used for tearing down unit tests.
> >      *
> > @@ -82,6 +90,7 @@
> >     static void removeMessageProvider(String providerId) {
> >         messageProviders.remove(providerId);
> >     }
> > +
> >     /**
> >      * Iterates over all registered message providers in order to find
> the
> > given
> >      * entry in the requested message bundle.
> > @@ -149,6 +158,64 @@
> >     }
> >
> >     /**
> > +     * Tries to find the desired entry in the named message provider.
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param id
> > +     *            The identifier that will be used to retrieve the
> > message
> > +     *            bundle
> > +     * @param entry
> > +     *            The desired message entry
> > +     * @param arguments
> > +     *            The dynamic parts of the message that will be
> evaluated
> > using
> > +     *            the standard java text formatting abilities.
> > +     * @param locale
> > +     *            The locale in which the message will be printed
> > +     * @exception MessageNotFoundException
> > +     *                Will be thrown if the requested message provider
> > cannot be found or
> > +     *                no message bundle can be found for the given id
> or
> > if the desired
> > +     *                message entry is missing in the retrieved bundle
> > +     * @return The localized text
> > +     */
> > +    public static String getText(String providerId, String id, String
> > entry, Object[] arguments,
> > +            Locale locale) throws MessageNotFoundException {
> > +        MessageProvider provider = (MessageProvider)
> > messageProviders.get(providerId);
> > +        if(provider == null)
> > +            throw new MessageNotFoundException("Provider '" +
> providerId
> > + "' not installed");
> > +        String text = provider.getText(id, entry, locale);
> > +        return MessageFormat.format(text, arguments);
> > +    }
> > +
> > +    /**
> > +     * Iterates over all registered message providers in order to find
> > the given
> > +     * entry in the requested message bundle.
> > +     *
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param id
> > +     *            The identifier that will be used to retrieve the
> > message
> > +     *            bundle
> > +     * @param entry
> > +     *            The desired message entry
> > +     * @param arguments
> > +     *            The dynamic parts of the message that will be
> evaluated
> > using
> > +     *            the standard java text formatting abilities.
> > +     * @param locale
> > +     *            The locale in which the message will be printed
> > +     * @param defaultText
> > +     *            If no message bundle or message entry could be found
> > for the
> > +     *            specified parameters, the default text will be
> > returned.
> > +     * @return The localized text or the default text if the message
> > could not
> > +     *         be found
> > +     */
> > +    public static String getText(String providerId, String id, String
> > entry, Object[] arguments,
> > +            Locale locale, String defaultText) {
> > +        try {
> > +            return getText(providerId, id, entry, arguments, locale);
> > +        } catch (MessageNotFoundException e) {
> > +            return MessageFormat.format(defaultText, arguments);
> > +        }
> > +    }
> > +
> > +    /**
> >      * Returns a map containing all available message entries for the
> > given
> >      * locale. The map contains keys of type {@link String}containing
> the
> > keys
> >      * of the available message entries and values of type {@link
> String}
> > @@ -168,4 +235,18 @@
> >         }
> >         throw exception;
> >     }
> > +
> > +  /**
> > +   * Returns a map containing all available message entries for the
> given
> > +   * locale. The map contains keys of type {@link String}containing the
> > keys
> > +   * of the available message entries and values of type {@link String}
> > +   * containing the localized message entries.
> > +   */
> > +  public static Map getEntries(String providerId, String id, Locale
> > locale)
> > +          throws MessageNotFoundException {
> > +      MessageProvider provider = (MessageProvider)
> > messageProviders.get(providerId);
> > +      if(provider == null)
> > +          throw new MessageNotFoundException("Provider '" + providerId
> +
> > "' not installed");
> > +      return provider.getEntries(id, locale);
> > +  }
> > }
> > \ No newline at end of file
> > Index: src/java/org/apache/commons/i18n/LocalizedBundle.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/LocalizedBundle.java (revision
> > 170884)
> > +++ src/java/org/apache/commons/i18n/LocalizedBundle.java (working copy)
> > @@ -42,16 +42,25 @@
> > public class LocalizedBundle implements Serializable {
> >     public final static String ID = "id";
> >
> > +    protected String providerId;
> >     protected String id;
> >     protected Object[] arguments;
> >
> > +  /**
> > +   * @param providerId The name of the message provider (i.e. source)
> to
> > use for the message
> > +   * @param messageId The messageId refers the corresponding bundle in
> > the file containing
> > +   * the localized messages.
> > +   */
> > +  public LocalizedBundle(String providerId, String messageId) {
> > +      this(providerId, messageId, new Object[0]);
> > +  }
> > +
> >     /**
> >      * @param messageId The messageId refers the corresponding bundle in
> > the file containing
> >      * the localized messages.
> >      */
> >     public LocalizedBundle(String messageId) {
> > -        this.id = messageId;
> > -        this.arguments = new Object[0];
> > +        this(messageId, new Object[0]);
> >     }
> >
> >     /**
> > @@ -65,6 +74,19 @@
> >         this.arguments = arguments;
> >     }
> >
> > +  /**
> > +   * @param providerId The name of the message provider (i.e. source)
> to
> > use for the message
> > +   * @param messageId The messageId refers the corresponding bundle in
> > the file containing
> > +   * the localized messages.
> > +   * @param arguments An array of objects containing arguments for the
> > messages. These arguments
> > +   * are used to insert dynamic values into the localized messages.
> > +   */
> > +  public LocalizedBundle(String providerId, String messageId, Object[]
> > arguments) {
> > +    this.providerId = providerId;
> > +    this.id = messageId;
> > +      this.arguments = arguments;
> > +  }
> > +
> >     /**
> >      * @return returns the id of this bundle
> >      */
> > @@ -78,8 +100,15 @@
> >     public Object[] getArguments() {
> >     return arguments;
> >     }
> > -
> > +
> >     /**
> > +     * @return The name of the message provider (i.e. source) to use
> for
> > the message
> > +     */
> > +    public String getProviderId() {
> > +        return providerId;
> > +    }
> > +
> > +    /**
> >      * @param key the key of the specific message entry in the message
> > bundle
> >      * @param locale the locale for that this message should be rendered
> >      * @return returns the text of the desired message entry for the
> given
> > locale
> > @@ -87,7 +116,9 @@
> >      * in this bundle
> >      */
> >     public String getEntry(String key, Locale locale) throws
> > MessageNotFoundException {
> > -        return MessageManager.getText(id, key, arguments, locale);
> > +        return providerId != null ?
> > +            MessageManager.getText(providerId, id, key, arguments,
> > locale) :
> > +            MessageManager.getText(id, key, arguments, locale);
> >     }
> >
> >     /**
> > @@ -97,6 +128,8 @@
> >      * @return returns the text of the desired message entry for the
> given
> > locale
> >      */
> >     public String getEntry(String key, Locale locale, String
> defaultText)
> > {
> > -        return MessageManager.getText(id, key, arguments, locale,
> > defaultText);
> > +        return providerId != null ?
> > +            MessageManager.getText(providerId, id, key, arguments,
> > locale, defaultText) :
> > +            MessageManager.getText(id, key, arguments, locale,
> > defaultText);
> >     }
> > }
> > \ No newline at end of file
> > Index:
> src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> > (revision 170884)
> > +++ src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> > (working copy)
> > @@ -47,12 +47,9 @@
> >      * @see
> > org.apache.commons.i18n.MessageProvider#getText(java.lang.String,
> > java.lang.String, java.util.Locale)
> >      */
> >     public String getText(String id, String entry, Locale locale) throws
> > MessageNotFoundException {
> > -        // TODO: Revise try/catch
> >         try {
> >             ResourceBundle resourceBundle =
> > ResourceBundle.getBundle(baseName, locale);
> > -             return resourceBundle.getString(id+"."+entry);
> > -        } catch ( ClassCastException e ) {
> > -            // ignore all entries that are not of type String
> > +             return resourceBundle.getObject(id+"."+entry).toString();
> >         }
> >         catch ( MissingResourceException e ) {
> >             logger.log(
> > Index: src/java/org/apache/commons/i18n/bundles/ErrorBundle.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/bundles/ErrorBundle.java (revision
> > 170884)
> > +++ src/java/org/apache/commons/i18n/bundles/ErrorBundle.java (working
> > copy)
> > @@ -45,6 +45,14 @@
> >     }
> >
> >     /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     */
> > +    public ErrorBundle(String providerId, String messageId) {
> > +        super(providerId, messageId);
> > +    }
> > +
> > +    /**
> >      * @param messageId Unique message id that identifies the message
> >      * @param arguments An array of objects conaining the values that
> > should be
> >      * inserted into the localized message.
> > @@ -54,6 +62,16 @@
> >     }
> >
> >     /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     * @param arguments An array of objects conaining the values that
> > should be
> > +     * inserted into the localized message.
> > +     */
> > +    public ErrorBundle(String providerId, String messageId, Object[]
> > arguments) {
> > +        super(providerId, messageId, arguments);
> > +    }
> > +
> > +    /**
> >      * @param locale The locale that is used to find the appropriate
> > localized text
> >      * @return returns the localized message entry with the key
> > <code>summary</code>
> >      * @throws MessageNotFoundException is thrown if no entry with key
> > <code>summary</code> could be found in the message bundle identified by
> > the given message identifier
> > Index: src/java/org/apache/commons/i18n/bundles/TextBundle.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/bundles/TextBundle.java (revision
> > 170884)
> > +++ src/java/org/apache/commons/i18n/bundles/TextBundle.java (working
> > copy)
> > @@ -44,6 +44,14 @@
> >     }
> >
> >     /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     */
> > +    public TextBundle(String providerId, String messageId) {
> > +        super(providerId, messageId);
> > +    }
> > +
> > +    /**
> >      * @param messageId Unique message id that identifies the message
> >      * @param arguments An array of objects conaining the values that
> > should be
> >      * inserted into the localized message.
> > @@ -53,6 +61,16 @@
> >     }
> >
> >     /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     * @param arguments An array of objects conaining the values that
> > should be
> > +     * inserted into the localized message.
> > +     */
> > +    public TextBundle(String providerId, String messageId, Object[]
> > arguments) {
> > +        super(providerId, messageId, arguments);
> > +    }
> > +
> > +    /**
> >      * @param locale The locale that is used to find the appropriate
> > localized text
> >      * @return returns the localized message entry with the key
> > <code>text</code>
> >      * @throws MessageNotFoundException is thrown if no entry with key
> > <code>text</code> could be found in the message bundle identified by the
> > given message identifier
> > Index: src/java/org/apache/commons/i18n/bundles/MessageBundle.java
> > ===================================================================
> > --- src/java/org/apache/commons/i18n/bundles/MessageBundle.java
> (revision
> > 170884)
> > +++ src/java/org/apache/commons/i18n/bundles/MessageBundle.java (working
> > copy)
> > @@ -42,6 +42,14 @@
> >     }
> >
> >     /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     */
> > +    public MessageBundle(String providerId, String messageId) {
> > +        super(providerId, messageId);
> > +    }
> > +
> > +    /**
> >      * @param messageId Unique message id that identifies the message
> >      * @param arguments An array of objects conaining the values that
> > should be
> >      * inserted into the localized message.
> > @@ -50,6 +58,15 @@
> >         super(messageId, arguments);
> >     }
> >
> > +    /**
> > +     * @param providerId The name of the message provider (i.e. source)
> > to use for the message
> > +     * @param messageId Unique message id that identifies the message
> > +     * @param arguments An array of objects conaining the values that
> > should be
> > +     * inserted into the localized message.
> > +     */
> > +    public MessageBundle(String providerId, String messageId, Object[]
> > arguments) {
> > +        super(providerId, messageId, arguments);
> > +    }
> >
> >     /**
> >      * @param locale The locale that is used to find the appropriate
> > localized text
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >
> >
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [i18n PATCH] Adding provider qualifying

Posted by James Mitchell <jm...@apache.org>.
I'm happy to help.

But, to be honest, I'm a bit disappointed at how this project is being 
developed.  I feel that i18n would benefit tremendously by reusing instead 
of reinventing.  As was pointed out months ago, there's just too much you 
get for free by leveraging other components and communities.

With all do respect to those of you working on i18n, I'm not currently using 
this component in my own work, but I plan to in the near future.  At that 
time I'll most likely fork the code, strip out the bottom half (dealing with 
message retrieval) and plug in commons-resources.  I have no interest in 
trying to redo my work from Commons Resources or reimplement the 3 
Database-based impls of such.  And what about the hundreds of JUnit tests. 
One thing I've been working on lately is getting Resources to 100% test 
coverage.  I would hate to ask someone to redo their work because I "didn't 
want to depend on another project".

Thanks.

--
James Mitchell
Software Engineer / Open Source Evangelist
Consulting / Mentoring / Freelance
EdgeTech, Inc.
http://www.edgetechservices.net/
678.910.8017
AIM:   jmitchtx
Yahoo: jmitchtx
MSN:   jmitchell@apache.org




----- Original Message ----- 
From: "Mattias J" <ma...@expertsystem.se>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>; 
"Daniel Florey" <da...@web.de>
Sent: Thursday, May 19, 2005 3:13 AM
Subject: [i18n PATCH] Adding provider qualifying


>I have previously discussed with Daniel Florey a change that allows the 
>user to qualify the provider (or source or namespace) to be used for a 
>given text entry. My main motivation for this is to allow the same entry 
>key in several different text sources, but this also provides better 
>performance since the API does not have to loop over the different 
>providers in search for the given entry.
>
> Thanks to James Mitchell I am now able to create the diff for this change; 
> see below. I would be happy if Daniel or anybody else would review and 
> commit this patch.
>
> Included in the patch is also a minor change that allows non-string 
> ResourceBundle entries to be used (via toString()).
>
> After this there are a few more changes I would like to discuss - 
> conserning class and package dependencies among others - so Daniel, please 
> tell me when you are available again. I also hope to find the time to 
> create an example DatabaseProvider.
>
> Now here is the diff.
> (Again, if lines are wrapped in the e-mail, I can provide the diff by 
> personal e-mail or in a bugzilla entry).
>
> Index: src/test/org/apache/commons/i18n/MockProviderTestBase.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/MockProviderTestBase.java (revision 
> 170884)
> +++ src/test/org/apache/commons/i18n/MockProviderTestBase.java (working 
> copy)
> @@ -30,36 +30,41 @@
>  * @author Mattias Jiderhamn
>  */
> public abstract class MockProviderTestBase extends TestCase {
> -    /**
> -     * Mock message provider that returns a string made up of the 
> arguments passed to it.
> -     */
> -    final private MessageProvider mockMessageProvider = new 
> MessageProvider() {
> -        public String getText(String id, String entry, Locale locale) 
> throws MessageNotFoundException {
> -            return MockProviderTestBase.getMockString(id, entry, locale);
> -        }
>
> -        public Map getEntries(String id, Locale locale) throws 
> MessageNotFoundException {
> -            Map output = new HashMap();
> -            output.put("entry1", 
> MockProviderTestBase.getMockString(id,"entry1",locale));
> -            output.put("entry2", 
> MockProviderTestBase.getMockString(id,"entry2",locale));
> -            return output;
> -        }
> -    };
> -
>     public void tearDown() {
>         /* Remove mock provider after each test, to allow for 
> MessageNotFoundExceptions */
> -        MessageManager.removeMessageProvider("mock");
> -        removeThrowingMockProvider();
> +        MessageManager.clearMessageProviders();
>     }
>
>     /**
>      * Add mock provider to <code>MessageManager</code>.
>      */
>     protected void addMockProvider() {
> -        MessageManager.addMessageProvider("mock", mockMessageProvider);
> +        addMockProvider("mock");
>     }
>
>     /**
> +     * Add mock provider to <code>MessageManager</code>.
> +     */
> +    protected void addMockProvider(final String providerId) {
> +         //  Mock message provider that returns a string made up of the 
> arguments passed to it.
> +        MessageProvider mockMessageProvider = new MessageProvider() {
> +            public String getText(String id, String entry, Locale locale) 
> throws MessageNotFoundException {
> +                return MockProviderTestBase.getMockString(providerId, id, 
> entry, locale);
> +            }
> +
> +            public Map getEntries(String id, Locale locale) throws 
> MessageNotFoundException {
> +                Map output = new HashMap();
> +                output.put("entry1", 
> MockProviderTestBase.getMockString(providerId,id,"entry1",locale));
> +                output.put("entry2", 
> MockProviderTestBase.getMockString(providerId,id,"entry2",locale));
> +                return output;
> +            }
> +        };
> +
> +        MessageManager.addMessageProvider(providerId, 
> mockMessageProvider);
> +    }
> +
> +    /**
>      * Add provider that always throws error to 
> <code>MessageManager</code>.
>      */
>     protected void addThrowingMockProvider() {
> @@ -82,10 +87,19 @@
>     // Utility methods
> 
> ////////////////////////////////////////////////////////////////////////
>
> +    public static String getMockString(String providerId, String id, 
> String entry, Locale locale) throws MessageNotFoundException {
> +        return ((providerId != null) ? "Source=" + providerId + " " : "") 
> +
> +                "Id=" + id + " Entry=" + entry + " Locale=" + locale + 
> "";
> +    }
> +
>     public static String getMockString(String id, String entry, Locale 
> locale) throws MessageNotFoundException {
> -        return "Id=" + id + " Entry=" + entry + " Locale=" + locale + "";
> +        return getMockString("mock", id, entry, locale);
>     }
>
> +    public static String getFormattedMockString(String providerId, String 
> id, String entry, String[] arguments, Locale locale) {
> +        return MessageFormat.format(getMockString(providerId, id, entry, 
> locale), arguments);
> +    }
> +
>     public static String getFormattedMockString(String id, String entry, 
> String[] arguments, Locale locale) {
>         return MessageFormat.format(getMockString(id, entry, locale), 
> arguments);
>     }
> Index: src/test/org/apache/commons/i18n/MessageManagerTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/MessageManagerTest.java (revision 
> 170884)
> +++ src/test/org/apache/commons/i18n/MessageManagerTest.java (working 
> copy)
> @@ -55,26 +55,48 @@
>
>         addMockProvider(); // Add mock provider
>
> -        assertEquals("Throwing mock not used", "Id=dummyId 
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Throwing mock not used", "Source=mock Id=dummyId 
> Entry=dummyEntry Locale=en_US",
>                 MessageManager.getText("dummyId", "dummyEntry", null, 
> Locale.US, "defaultText"));
>
>         removeThrowingMockProvider(); // Removing throwing mock and keep 
> only normal mock
>
> -        assertEquals("Default text not used", "Id=dummyId 
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Default text not used", "Source=mock Id=dummyId 
> Entry=dummyEntry Locale=en_US",
>                 MessageManager.getText("dummyId", "dummyEntry", null, 
> Locale.US, "defaultText"));
>
> -        assertEquals("Normal lookup", "Id=id Entry=entry Locale=en_US",
> +        assertEquals("Normal lookup", "Source=mock Id=id Entry=entry 
> Locale=en_US",
>                 MessageManager.getText("id", "entry", null, Locale.US));
>         assertEquals("Single argument",
> -                "Id=id Entry=entry value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
>                 MessageManager.getText("id", "entry {0}", new String[] 
> {"value1"}, Locale.US));
>         assertEquals("Multiple arguments",
> -                "Id=id Entry=entry value0: value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value0: value1 
> Locale=en_US",
>                 MessageManager.getText("id", "entry {0}: {1}", new 
> String[] {"value0", "value1"},Locale.US));
>
>         assertEquals("Single argument and default",
> -                "Id=id Entry=entry value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
>                 MessageManager.getText("id", "entry {0}", new String[] 
> {"value1"},Locale.US, "defaultText"));
> +
> +        // Named provider not found
> +        try {
> +            MessageManager.getText("mockProvider2", "dummyId", 
> "dummyEntry", null, Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'mockProvider2' not 
> installed", mnfex.getMessage());
> +        }
> +
> +        assertEquals("Default text used", "defaultText",
> +                MessageManager.getText("mockProvider2", "dummyId", 
> "dummyEntry", null, Locale.US, "defaultText"));
> +
> +
> +        // Named provider found
> +        addMockProvider("mockProvider2");
> +
> +        assertEquals("Default text not used, qualified lookup", 
> "Source=mockProvider2 Id=dummyId Entry=dummyEntry Locale=en_US",
> +                MessageManager.getText("mockProvider2", "dummyId", 
> "dummyEntry", null, Locale.US, "defaultText"));
> +
> +        assertEquals("Normal qualified lookup", "Source=mockProvider2 
> Id=id Entry=entry Locale=en_US",
> +                MessageManager.getText("mockProvider2", "id", "entry", 
> null, Locale.US));
>     }
>
>     public void testGetEntries() {
> @@ -100,8 +122,8 @@
>
>         Map entries = MessageManager.getEntries("dummyId", Locale.US);
>         assertEquals("No of entries", 2, entries.size());
> -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1 
> Locale=en_US", entries.get("entry1"));
> -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2 
> Locale=en_US", entries.get("entry2"));
> +        assertEquals("Entry 1 match", "Source=mock Id=dummyId 
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mock Id=dummyId 
> Entry=entry2 Locale=en_US", entries.get("entry2"));
>
>         removeThrowingMockProvider(); // Removing throwing mock and keep 
> only normal mock
>
> @@ -109,7 +131,24 @@
>
>         entries = MessageManager.getEntries("dummyId", Locale.US);
>         assertEquals("No of entries", 2, entries.size());
> -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1 
> Locale=en_US", entries.get("entry1"));
> -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2 
> Locale=en_US", entries.get("entry2"));
> +        assertEquals("Entry 1 match", "Source=mock Id=dummyId 
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mock Id=dummyId 
> Entry=entry2 Locale=en_US", entries.get("entry2"));
> +
> +        // Named provider not found
> +        try {
> +            MessageManager.getEntries("mockProvider2", "dummyId", 
> Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'mockProvider2' not 
> installed", mnfex.getMessage());
> +        }
> +
> +        // Named provider found
> +        addMockProvider("mockProvider2");
> +
> +        entries = MessageManager.getEntries("mockProvider2", "dummyId", 
> Locale.US);
> +        assertEquals("No of entries", 2, entries.size());
> +        assertEquals("Entry 1 match", "Source=mockProvider2 Id=dummyId 
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mockProvider2 Id=dummyId 
> Entry=entry2 Locale=en_US", entries.get("entry2"));
>     }
> }
> \ No newline at end of file
> Index: src/test/org/apache/commons/i18n/LocalizedBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/LocalizedBundleTest.java (revision 
> 170884)
> +++ src/test/org/apache/commons/i18n/LocalizedBundleTest.java (working 
> copy)
> @@ -24,21 +24,38 @@
> public class LocalizedBundleTest extends MockProviderTestBase {
>     public void testConstructors() {
>         LocalizedBundle lb = new LocalizedBundle("dummyId1");
> +        assertNull("No provider", lb.getProviderId());
>         assertEquals("Id set", "dummyId1", lb.getId());
>         assertNotNull("Arguments not null", lb.getArguments());
>         assertEquals("No arguments", 0, lb.getArguments().length);
>
> +        LocalizedBundle lbProvider = new 
> LocalizedBundle("dummyProvider2", "dummyId2");
> +        assertEquals("Provider set", "dummyProvider2", 
> lbProvider.getProviderId());
> +        assertEquals("Id set", "dummyId2", lbProvider.getId());
> +        assertNotNull("Arguments not null", lbProvider.getArguments());
> +        assertEquals("No arguments", 0, 
> lbProvider.getArguments().length);
> +
>         String[] arguments = new String[]{"arg1", "arg2"};
> -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", 
> arguments);
> -        assertEquals("Id set", "dummyId2", lbArgs.getId());
> +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", 
> arguments);
> +        assertNull("No provider", lbArgs.getProviderId());
> +        assertEquals("Id set", "dummyId3", lbArgs.getId());
>         assertNotNull("Arguments not null", lbArgs.getArguments());
>         assertEquals("No of arguments", 2, lbArgs.getArguments().length);
>         assertEquals("Arguments", arguments, lbArgs.getArguments());
> +
> +        LocalizedBundle lbProviderArgs = new 
> LocalizedBundle("dummyProvider4", "dummyId4", arguments);
> +        assertEquals("Provider set", "dummyProvider4", 
> lbProviderArgs.getProviderId());
> +        assertEquals("Id set", "dummyId4", lbProviderArgs.getId());
> +        assertNotNull("Arguments not null", 
> lbProviderArgs.getArguments());
> +        assertEquals("No of arguments", 2, 
> lbProviderArgs.getArguments().length);
> +        assertEquals("Arguments", arguments, 
> lbProviderArgs.getArguments());
>     }
>
>     public void testGetEntry() {
>         LocalizedBundle lb = new LocalizedBundle("dummyId1");
> -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", new 
> String[] {"arg1", "arg2"});
> +        LocalizedBundle lbProvider = new 
> LocalizedBundle("dummyProvider2", "dummyId2");
> +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", new 
> String[] {"arg1", "arg2"});
> +        LocalizedBundle lbProviderArgs = new 
> LocalizedBundle("dummyProvider4", "dummyId4", new String[] {"arg1", 
> "arg2"});
>
>         // Test errors
>         try {
> @@ -63,15 +80,53 @@
>
>         addMockProvider(); // Add mock provider
>
> -        assertEquals("Default text not used", "Id=dummyId1 
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Default text not used", getMockString("dummyId1", 
> "dummyEntry", Locale.US),
>                 lb.getEntry("dummyEntry", Locale.US, "defaltText"));
>
> -        assertEquals("Normal lookup", "Id=dummyId1 Entry=entry 
> Locale=en_US", lb.getEntry("entry", Locale.US));
> -        assertEquals("Arguments missing", "Id=dummyId1 Entry=entry {0} 
> Locale=en_US",
> +        assertEquals("Normal lookup", getMockString("dummyId1", "entry", 
> Locale.US), lb.getEntry("entry", Locale.US));
> +        assertEquals("Arguments missing", "Source=mock Id=dummyId1 
> Entry=entry {0} Locale=en_US",
>                 lb.getEntry("entry {0}", Locale.US));
> -        assertEquals("Argument", "Id=dummyId2 Entry=entry arg1 arg2 
> Locale=en_US",
> +        assertEquals("Argument", "Source=mock Id=dummyId3 Entry=entry 
> arg1 arg2 Locale=en_US",
>                 lbArgs.getEntry("entry {0} {1}", Locale.US));
> -        assertEquals("Arguments and default", "Id=dummyId2 Entry=entry 
> arg1 arg2 Locale=en_US",
> +        assertEquals("Arguments and default", "Source=mock Id=dummyId3 
> Entry=entry arg1 arg2 Locale=en_US",
>                 lbArgs.getEntry("entry {0} {1}", Locale.US, 
> "defaultText"));
> +
> +        // Named provider not found
> +        try {
> +            lbProvider.getEntry("dummyEntry", Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'dummyProvider2' not 
> installed", mnfex.getMessage());
> +        }
> +
> +        try {
> +            lbProviderArgs.getEntry("dummyEntry", Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'dummyProvider4' not 
> installed", mnfex.getMessage());
> +        }
> +
> +        assertEquals("Default text", "defaultText", 
> lbProvider.getEntry("dummyEntry", Locale.US, "defaultText"));
> +        assertEquals("Default text", "defaultText", 
> lbProviderArgs.getEntry("dummyEntry", Locale.US, "defaultText"));
> +
> +        // Named provider found
> +        addMockProvider("dummyProvider2");
> +        addMockProvider("dummyProvider4");
> +
> +        assertEquals("Named provider: Default text not used",
> +                getMockString("dummyProvider2", "dummyId2", "dummyEntry", 
> Locale.US),
> +                lbProvider.getEntry("dummyEntry", Locale.US, 
> "defaltText"));
> +
> +        assertEquals("Named provider: Normal lookup", 
> getMockString("dummyProvider2", "dummyId2", "entry", Locale.US),
> +                lbProvider.getEntry("entry", Locale.US));
> +        assertEquals("Named provider: Arguments missing", 
> "Source=dummyProvider2 Id=dummyId2 Entry=entry {0} Locale=en_US",
> +                lbProvider.getEntry("entry {0}", Locale.US));
> +        assertEquals("Named provider: Argument", "Source=dummyProvider4 
> Id=dummyId4 Entry=entry arg1 arg2 Locale=en_US",
> +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US));
> +        assertEquals("Named provider: Arguments and default",
> +                "Source=dummyProvider4 Id=dummyId4 Entry=entry arg1 arg2 
> Locale=en_US",
> +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US, 
> "defaultText"));
>     }
> }
> Index: src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/XMLMessageProviderTest.java (revision 
> 170884)
> +++ src/test/org/apache/commons/i18n/XMLMessageProviderTest.java (working 
> copy)
> @@ -2,7 +2,7 @@
> *
> * ====================================================================
> *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -56,12 +56,12 @@
>         }
>
>         XMLMessageProvider.install("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
>
>         assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
>
>         XMLMessageProvider.update("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
>
>         assertEquals("OK after update", "Hallo Welt", 
> testMessage.getTitle(Locale.GERMAN));
>
> @@ -77,14 +77,14 @@
>
>         // Try to parse non-XML file
>         XMLMessageProvider.install("org.apache.commons-i18n.error",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messageBundle.properties"));
>     }
> -
> +
>     public void testGetText() {
> //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> -// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
> +// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
>         XMLMessageProvider xmlmp = new 
> XMLMessageProvider("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
>
>         assertEquals("Default locale", "hello world", 
> xmlmp.getText("helloWorld", "title", Locale.US));
>         assertEquals("Default locale", "hello world", 
> xmlmp.getText("helloWorld", "title", Locale.UK));
> @@ -123,9 +123,9 @@
>
>     public void testGetTextVariants() {
> //        XMLMessageProvider.install("org.apache.commons-i18n.variants",
> -// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
> +// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
>         XMLMessageProvider xmlmp = new 
> XMLMessageProvider("org.apache.commons-i18n.variants",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("variantTestMessages.xml"));
>
>         assertEquals("hello world", xmlmp.getText("variants", "theKey", 
> Locale.ENGLISH));
>         assertEquals("Botswana", "Hello Botswana", 
> xmlmp.getText("variants", "theKey", new Locale("", "BW")));
> @@ -135,9 +135,9 @@
>
>     public void testGetEntries() {
> //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> -// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
> +// 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml"));
>         Map usEntries = new 
> XMLMessageProvider("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
>                     getEntries("helloWorld", Locale.US);
>         assertEquals("Default locale, no of entries", 5, 
> usEntries.size());
>         assertEquals("Default locale, titel", "hello world", 
> usEntries.get("title"));
> @@ -151,7 +151,7 @@
>         assertEquals("This entry is not translated to any other languages 
> (XML)", usEntries.get("notTranslated"));
>
>         Map germanEntries = new 
> XMLMessageProvider("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
>                     getEntries("helloWorld", Locale.GERMAN);
>         assertEquals("No of entries", 4, germanEntries.size());
>         assertEquals("Hallo Welt", germanEntries.get("title"));
> @@ -163,7 +163,7 @@
> //        assertEquals("This entry is not translated to any other 
> languages", germanEntries.get("notTranslated"));
>
>         Map japaneseEntries = new 
> XMLMessageProvider("org.apache.commons-i18n.test",
> - 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
> + 
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMessages.xml")).
>                     getEntries("helloWorld", Locale.JAPANESE);
>         assertEquals("Fallback locale, no of entries", 5, 
> japaneseEntries.size());
>
> Index: 
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> ===================================================================
> ---  
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java 
> (revision 170884)
> +++ 
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java 
> (working copy)
> @@ -2,7 +2,7 @@
> *
> * ====================================================================
> *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -45,7 +45,7 @@
>         ResourceBundleMessageProvider.uninstall("messageBundle");
>         ResourceBundleMessageProvider.uninstall("messageBundle2");
>         ResourceBundleMessageProvider.uninstall("nonExistentBundle");
> - 
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListResourceBundle");
> + 
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListResourceBundle");
>     }
>
>     public void testInstallResourceBundle() {
> @@ -89,17 +89,11 @@
>
>         // Test with list resource bundle
> //        ResourceBundleMessageProvider.uninstall("messageBundle"); // 
> Remove
> -// 
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResourceBundle"); 
> // Install ListResourceBundle
> +// 
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResourceBundle"); 
> // Install ListResourceBundle
>         ResourceBundleMessageProvider listResourceBundleProvider =
>                 new 
> ResourceBundleMessageProvider("org.apache.commons.i18n.MyListResourceBundle"); 
> // Install ListResourceBundle
>         assertEquals("Value from ListResourceBundle", "listResourceValue", 
> listResourceBundleProvider.getText("helloWorld", "title", Locale.US));
> -        try {
> -            String s = listResourceBundleProvider.getText("helloWorld", 
> "text", Locale.US);
> -            fail("Entry should not be found, since it is numeric. Found 
> text: " + s);
> -        }
> -        catch(MessageNotFoundException mnfex) {
> -            assertEquals("No message entries found for bundle with key 
> helloWorld", mnfex.getMessage());
> -        }
> +        assertEquals("Value from ListResourceBundle", "1", 
> listResourceBundleProvider.getText("helloWorld", "text", Locale.US));
>
>         try {
>             rbmp.getText("nonExistentId", "nonExistentEntry", Locale.US);
> Index: src/test/org/apache/commons/i18n/I18nTestSuite.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/I18nTestSuite.java (revision 170884)
> +++ src/test/org/apache/commons/i18n/I18nTestSuite.java (working copy)
> @@ -2,7 +2,7 @@
> *
> * ====================================================================
> *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> Index: src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java 
> (revision 170884)
> +++ src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java (working 
> copy)
> @@ -52,6 +52,38 @@
>                 eb.getDetails(Locale.US, "defaultText"));
>     }
>
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId");
> +        try {
> +            eb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText", eb.getText(Locale.US, 
> "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.TEXT, Locale.US),
> +                eb.getText(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.TITLE, Locale.US),
> +                eb.getTitle(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.SUMMARY, Locale.US),
> +                eb.getSummary(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.DETAILS, Locale.US),
> +                eb.getDetails(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.TEXT, Locale.US),
> +                eb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.TITLE, Locale.US),
> +                eb.getTitle(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.SUMMARY, Locale.US),
> +                eb.getSummary(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", ErrorBundle.DETAILS, Locale.US),
> +                eb.getDetails(Locale.US, "defaultText"));
> +    }
> +
>     public void testWithArguments() {
>         String[] arguments = new String[]{"arg1", "arg2"};
>         ErrorBundle eb = new ErrorBundle("dummyId", arguments);
> @@ -83,4 +115,45 @@
>         assertEquals("Default not used", getFormattedMockString("dummyId", 
> ErrorBundle.DETAILS, arguments, Locale.US),
>                 eb.getDetails(Locale.US, "defaultText"));
>     }
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId", 
> arguments);
> +        try {
> +            eb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2", 
> eb.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.TEXT, arguments, Locale.US),
> +                eb.getText(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.TITLE, arguments, Locale.US),
> +                eb.getTitle(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.SUMMARY, arguments, Locale.US),
> +                eb.getSummary(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.DETAILS, arguments, Locale.US),
> +                eb.getDetails(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.TEXT, arguments, Locale.US),
> +                eb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.TITLE, arguments, Locale.US),
> +                eb.getTitle(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.SUMMARY, arguments, Locale.US),
> +                eb.getSummary(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> ErrorBundle.DETAILS, arguments, Locale.US),
> +                eb.getDetails(Locale.US, "defaultText"));
> +    }
> }
> \ No newline at end of file
> Index: src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java 
> (revision 170884)
> +++ src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java 
> (working copy)
> @@ -46,6 +46,30 @@
>                 mb.getTitle(Locale.US, "defaultText"));
>     }
>
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId");
> +        try {
> +            mb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText", mb.getText(Locale.US, 
> "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", MessageBundle.TEXT, Locale.US),
> +                mb.getText(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", MessageBundle.TITLE, Locale.US),
> +                mb.getTitle(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", MessageBundle.TEXT, Locale.US),
> +                mb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", MessageBundle.TITLE, Locale.US),
> +                mb.getTitle(Locale.US, "defaultText"));
> +    }
> +
>     public void testWithArguments() {
>         String[] arguments = new String[]{"arg1", "arg2"};
>         MessageBundle mb = new MessageBundle("dummyId", arguments);
> @@ -69,4 +93,33 @@
>         assertEquals("Default not used", getFormattedMockString("dummyId", 
> MessageBundle.TITLE, arguments, Locale.US),
>                 mb.getTitle(Locale.US, "defaultText"));
>     }
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId", 
> arguments);
> +        try {
> +            mb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2", 
> mb.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> MessageBundle.TEXT, arguments, Locale.US),
> +                mb.getText(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> MessageBundle.TITLE, arguments, Locale.US),
> +                mb.getTitle(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> MessageBundle.TEXT, arguments, Locale.US),
> +                mb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> MessageBundle.TITLE, arguments, Locale.US),
> +                mb.getTitle(Locale.US, "defaultText"));
> +    }
> }
> Index: src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/TextBundleTest.java (revision 
> 170884)
> +++ src/test/org/apache/commons/i18n/bundles/TextBundleTest.java (working 
> copy)
> @@ -43,6 +43,26 @@
>                 textBundle.getText(Locale.US, "defaultText"));
>     }
>
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        TextBundle textBundle = new TextBundle("dummyProvider", 
> "dummyId");
> +        try {
> +            textBundle.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText", 
> textBundle.getText(Locale.US, "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider", 
> "dummyId", TextBundle.TEXT, Locale.US),
> +                textBundle.getText(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider", 
> "dummyId", TextBundle.TEXT, Locale.US),
> +                textBundle.getText(Locale.US, "defaultText"));
> +    }
> +
>     public void testWithArguments() {
>         String[] arguments = new String[]{"arg1", "arg2"};
>         TextBundle textBundle = new TextBundle("dummyId", arguments);
> @@ -62,4 +82,26 @@
>         assertEquals("Default not used", getFormattedMockString("dummyId", 
> TextBundle.TEXT, arguments, Locale.US),
>                 textBundle.getText(Locale.US, "defaultText"));
>     }
> -}
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        TextBundle textBundle = new TextBundle("dummyProvider", 
> "dummyId", arguments);
> +        try {
> +            textBundle.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed", 
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2", 
> textBundle.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> TextBundle.TEXT, arguments, Locale.US),
> +                textBundle.getText(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId", 
> TextBundle.TEXT, arguments, Locale.US),
> +                textBundle.getText(Locale.US, "defaultText"));
> +    }}
> Index: src/java/org/apache/commons/i18n/MessageManager.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/MessageManager.java (revision 170884)
> +++ src/java/org/apache/commons/i18n/MessageManager.java (working copy)
> @@ -74,6 +74,14 @@
>     }
>
>     /**
> +     * Remove all <code>{@link MessageProvider}</code>s from the
> +     * <code>MessageManager</code>. Used for tearing down unit tests.
> +     */
> +    static void clearMessageProviders() {
> +        messageProviders.clear();
> +    }
> +
> +    /**
>      * Remove custom <code>{@link MessageProvider}</code> from the
>      * <code>MessageManager</code>. Used for tearing down unit tests.
>      *
> @@ -82,6 +90,7 @@
>     static void removeMessageProvider(String providerId) {
>         messageProviders.remove(providerId);
>     }
> +
>     /**
>      * Iterates over all registered message providers in order to find the 
> given
>      * entry in the requested message bundle.
> @@ -149,6 +158,64 @@
>     }
>
>     /**
> +     * Tries to find the desired entry in the named message provider.
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param id
> +     *            The identifier that will be used to retrieve the 
> message
> +     *            bundle
> +     * @param entry
> +     *            The desired message entry
> +     * @param arguments
> +     *            The dynamic parts of the message that will be evaluated 
> using
> +     *            the standard java text formatting abilities.
> +     * @param locale
> +     *            The locale in which the message will be printed
> +     * @exception MessageNotFoundException
> +     *                Will be thrown if the requested message provider 
> cannot be found or
> +     *                no message bundle can be found for the given id or 
> if the desired
> +     *                message entry is missing in the retrieved bundle
> +     * @return The localized text
> +     */
> +    public static String getText(String providerId, String id, String 
> entry, Object[] arguments,
> +            Locale locale) throws MessageNotFoundException {
> +        MessageProvider provider = (MessageProvider) 
> messageProviders.get(providerId);
> +        if(provider == null)
> +            throw new MessageNotFoundException("Provider '" + providerId 
> + "' not installed");
> +        String text = provider.getText(id, entry, locale);
> +        return MessageFormat.format(text, arguments);
> +    }
> +
> +    /**
> +     * Iterates over all registered message providers in order to find 
> the given
> +     * entry in the requested message bundle.
> +     *
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param id
> +     *            The identifier that will be used to retrieve the 
> message
> +     *            bundle
> +     * @param entry
> +     *            The desired message entry
> +     * @param arguments
> +     *            The dynamic parts of the message that will be evaluated 
> using
> +     *            the standard java text formatting abilities.
> +     * @param locale
> +     *            The locale in which the message will be printed
> +     * @param defaultText
> +     *            If no message bundle or message entry could be found 
> for the
> +     *            specified parameters, the default text will be 
> returned.
> +     * @return The localized text or the default text if the message 
> could not
> +     *         be found
> +     */
> +    public static String getText(String providerId, String id, String 
> entry, Object[] arguments,
> +            Locale locale, String defaultText) {
> +        try {
> +            return getText(providerId, id, entry, arguments, locale);
> +        } catch (MessageNotFoundException e) {
> +            return MessageFormat.format(defaultText, arguments);
> +        }
> +    }
> +
> +    /**
>      * Returns a map containing all available message entries for the 
> given
>      * locale. The map contains keys of type {@link String}containing the 
> keys
>      * of the available message entries and values of type {@link String}
> @@ -168,4 +235,18 @@
>         }
>         throw exception;
>     }
> +
> +  /**
> +   * Returns a map containing all available message entries for the given
> +   * locale. The map contains keys of type {@link String}containing the 
> keys
> +   * of the available message entries and values of type {@link String}
> +   * containing the localized message entries.
> +   */
> +  public static Map getEntries(String providerId, String id, Locale 
> locale)
> +          throws MessageNotFoundException {
> +      MessageProvider provider = (MessageProvider) 
> messageProviders.get(providerId);
> +      if(provider == null)
> +          throw new MessageNotFoundException("Provider '" + providerId + 
> "' not installed");
> +      return provider.getEntries(id, locale);
> +  }
> }
> \ No newline at end of file
> Index: src/java/org/apache/commons/i18n/LocalizedBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/LocalizedBundle.java (revision 
> 170884)
> +++ src/java/org/apache/commons/i18n/LocalizedBundle.java (working copy)
> @@ -42,16 +42,25 @@
> public class LocalizedBundle implements Serializable {
>     public final static String ID = "id";
>
> +    protected String providerId;
>     protected String id;
>     protected Object[] arguments;
>
> +  /**
> +   * @param providerId The name of the message provider (i.e. source) to 
> use for the message
> +   * @param messageId The messageId refers the corresponding bundle in 
> the file containing
> +   * the localized messages.
> +   */
> +  public LocalizedBundle(String providerId, String messageId) {
> +      this(providerId, messageId, new Object[0]);
> +  }
> +
>     /**
>      * @param messageId The messageId refers the corresponding bundle in 
> the file containing
>      * the localized messages.
>      */
>     public LocalizedBundle(String messageId) {
> -        this.id = messageId;
> -        this.arguments = new Object[0];
> +        this(messageId, new Object[0]);
>     }
>
>     /**
> @@ -65,6 +74,19 @@
>         this.arguments = arguments;
>     }
>
> +  /**
> +   * @param providerId The name of the message provider (i.e. source) to 
> use for the message
> +   * @param messageId The messageId refers the corresponding bundle in 
> the file containing
> +   * the localized messages.
> +   * @param arguments An array of objects containing arguments for the 
> messages. These arguments
> +   * are used to insert dynamic values into the localized messages.
> +   */
> +  public LocalizedBundle(String providerId, String messageId, Object[] 
> arguments) {
> +    this.providerId = providerId;
> +    this.id = messageId;
> +      this.arguments = arguments;
> +  }
> +
>     /**
>      * @return returns the id of this bundle
>      */
> @@ -78,8 +100,15 @@
>     public Object[] getArguments() {
>     return arguments;
>     }
> -
> +
>     /**
> +     * @return The name of the message provider (i.e. source) to use for 
> the message
> +     */
> +    public String getProviderId() {
> +        return providerId;
> +    }
> +
> +    /**
>      * @param key the key of the specific message entry in the message 
> bundle
>      * @param locale the locale for that this message should be rendered
>      * @return returns the text of the desired message entry for the given 
> locale
> @@ -87,7 +116,9 @@
>      * in this bundle
>      */
>     public String getEntry(String key, Locale locale) throws 
> MessageNotFoundException {
> -        return MessageManager.getText(id, key, arguments, locale);
> +        return providerId != null ?
> +            MessageManager.getText(providerId, id, key, arguments, 
> locale) :
> +            MessageManager.getText(id, key, arguments, locale);
>     }
>
>     /**
> @@ -97,6 +128,8 @@
>      * @return returns the text of the desired message entry for the given 
> locale
>      */
>     public String getEntry(String key, Locale locale, String defaultText) 
> {
> -        return MessageManager.getText(id, key, arguments, locale, 
> defaultText);
> +        return providerId != null ?
> +            MessageManager.getText(providerId, id, key, arguments, 
> locale, defaultText) :
> +            MessageManager.getText(id, key, arguments, locale, 
> defaultText);
>     }
> }
> \ No newline at end of file
> Index: src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java 
> (revision 170884)
> +++ src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java 
> (working copy)
> @@ -47,12 +47,9 @@
>      * @see 
> org.apache.commons.i18n.MessageProvider#getText(java.lang.String, 
> java.lang.String, java.util.Locale)
>      */
>     public String getText(String id, String entry, Locale locale) throws 
> MessageNotFoundException {
> -        // TODO: Revise try/catch
>         try {
>             ResourceBundle resourceBundle = 
> ResourceBundle.getBundle(baseName, locale);
> -             return resourceBundle.getString(id+"."+entry);
> -        } catch ( ClassCastException e ) {
> -            // ignore all entries that are not of type String
> +             return resourceBundle.getObject(id+"."+entry).toString();
>         }
>         catch ( MissingResourceException e ) {
>             logger.log(
> Index: src/java/org/apache/commons/i18n/bundles/ErrorBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/ErrorBundle.java (revision 
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/ErrorBundle.java (working 
> copy)
> @@ -45,6 +45,14 @@
>     }
>
>     /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public ErrorBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>      * @param messageId Unique message id that identifies the message
>      * @param arguments An array of objects conaining the values that 
> should be
>      * inserted into the localized message.
> @@ -54,6 +62,16 @@
>     }
>
>     /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that 
> should be
> +     * inserted into the localized message.
> +     */
> +    public ErrorBundle(String providerId, String messageId, Object[] 
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
> +
> +    /**
>      * @param locale The locale that is used to find the appropriate 
> localized text
>      * @return returns the localized message entry with the key 
> <code>summary</code>
>      * @throws MessageNotFoundException is thrown if no entry with key 
> <code>summary</code> could be found in the message bundle identified by 
> the given message identifier
> Index: src/java/org/apache/commons/i18n/bundles/TextBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/TextBundle.java (revision 
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/TextBundle.java (working 
> copy)
> @@ -44,6 +44,14 @@
>     }
>
>     /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public TextBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>      * @param messageId Unique message id that identifies the message
>      * @param arguments An array of objects conaining the values that 
> should be
>      * inserted into the localized message.
> @@ -53,6 +61,16 @@
>     }
>
>     /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that 
> should be
> +     * inserted into the localized message.
> +     */
> +    public TextBundle(String providerId, String messageId, Object[] 
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
> +
> +    /**
>      * @param locale The locale that is used to find the appropriate 
> localized text
>      * @return returns the localized message entry with the key 
> <code>text</code>
>      * @throws MessageNotFoundException is thrown if no entry with key 
> <code>text</code> could be found in the message bundle identified by the 
> given message identifier
> Index: src/java/org/apache/commons/i18n/bundles/MessageBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/MessageBundle.java (revision 
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/MessageBundle.java (working 
> copy)
> @@ -42,6 +42,14 @@
>     }
>
>     /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public MessageBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>      * @param messageId Unique message id that identifies the message
>      * @param arguments An array of objects conaining the values that 
> should be
>      * inserted into the localized message.
> @@ -50,6 +58,15 @@
>         super(messageId, arguments);
>     }
>
> +    /**
> +     * @param providerId The name of the message provider (i.e. source) 
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that 
> should be
> +     * inserted into the localized message.
> +     */
> +    public MessageBundle(String providerId, String messageId, Object[] 
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
>
>     /**
>      * @param locale The locale that is used to find the appropriate 
> localized text
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


AW: [i18n PATCH] Adding provider qualifying

Posted by Daniel Florey <da...@web.de>.
Hi,
I try to have a look at the patch and the missing unit tests soon. I'm very
busy at the moment, but hopefully next week I'll find some time.
Thanks for your work!
Daniel

> -----Ursprüngliche Nachricht-----
> Von: commons-dev-return-71421-daniel.florey=web.de@jakarta.apache.org
> [mailto:commons-dev-return-71421-daniel.florey=web.de@jakarta.apache.org]
> Im Auftrag von Mattias J
> Gesendet: Donnerstag, 19. Mai 2005 09:13
> An: Jakarta Commons Developers List; Daniel Florey
> Betreff: [i18n PATCH] Adding provider qualifying
> 
> I have previously discussed with Daniel Florey a change that allows the
> user to qualify the provider (or source or namespace) to be used for a
> given text entry. My main motivation for this is to allow the same entry
> key in several different text sources, but this also provides better
> performance since the API does not have to loop over the different
> providers in search for the given entry.
> 
> Thanks to James Mitchell I am now able to create the diff for this change;
> see below. I would be happy if Daniel or anybody else would review and
> commit this patch.
> 
> Included in the patch is also a minor change that allows non-string
> ResourceBundle entries to be used (via toString()).
> 
> After this there are a few more changes I would like to discuss -
> conserning class and package dependencies among others - so Daniel, please
> tell me when you are available again. I also hope to find the time to
> create an example DatabaseProvider.
> 
> Now here is the diff.
> (Again, if lines are wrapped in the e-mail, I can provide the diff by
> personal e-mail or in a bugzilla entry).
> 
> Index: src/test/org/apache/commons/i18n/MockProviderTestBase.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/MockProviderTestBase.java
(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/MockProviderTestBase.java
(working
> copy)
> @@ -30,36 +30,41 @@
>   * @author Mattias Jiderhamn
>   */
>  public abstract class MockProviderTestBase extends TestCase {
> -    /**
> -     * Mock message provider that returns a string made up of the
> arguments passed to it.
> -     */
> -    final private MessageProvider mockMessageProvider = new
> MessageProvider() {
> -        public String getText(String id, String entry, Locale locale)
> throws MessageNotFoundException {
> -            return MockProviderTestBase.getMockString(id, entry, locale);
> -        }
> 
> -        public Map getEntries(String id, Locale locale) throws
> MessageNotFoundException {
> -            Map output = new HashMap();
> -            output.put("entry1",
> MockProviderTestBase.getMockString(id,"entry1",locale));
> -            output.put("entry2",
> MockProviderTestBase.getMockString(id,"entry2",locale));
> -            return output;
> -        }
> -    };
> -
>      public void tearDown() {
>          /* Remove mock provider after each test, to allow for
> MessageNotFoundExceptions */
> -        MessageManager.removeMessageProvider("mock");
> -        removeThrowingMockProvider();
> +        MessageManager.clearMessageProviders();
>      }
> 
>      /**
>       * Add mock provider to <code>MessageManager</code>.
>       */
>      protected void addMockProvider() {
> -        MessageManager.addMessageProvider("mock", mockMessageProvider);
> +        addMockProvider("mock");
>      }
> 
>      /**
> +     * Add mock provider to <code>MessageManager</code>.
> +     */
> +    protected void addMockProvider(final String providerId) {
> +         //  Mock message provider that returns a string made up of the
> arguments passed to it.
> +        MessageProvider mockMessageProvider = new MessageProvider() {
> +            public String getText(String id, String entry, Locale locale)
> throws MessageNotFoundException {
> +                return MockProviderTestBase.getMockString(providerId, id,
> entry, locale);
> +            }
> +
> +            public Map getEntries(String id, Locale locale) throws
> MessageNotFoundException {
> +                Map output = new HashMap();
> +                output.put("entry1",
> MockProviderTestBase.getMockString(providerId,id,"entry1",locale));
> +                output.put("entry2",
> MockProviderTestBase.getMockString(providerId,id,"entry2",locale));
> +                return output;
> +            }
> +        };
> +
> +        MessageManager.addMessageProvider(providerId,
> mockMessageProvider);
> +    }
> +
> +    /**
>       * Add provider that always throws error to
> <code>MessageManager</code>.
>       */
>      protected void addThrowingMockProvider() {
> @@ -82,10 +87,19 @@
>      // Utility methods
> 
> ////////////////////////////////////////////////////////////////////////
> 
> +    public static String getMockString(String providerId, String id,
> String entry, Locale locale) throws MessageNotFoundException {
> +        return ((providerId != null) ? "Source=" + providerId + " " : "")
> +
> +                "Id=" + id + " Entry=" + entry + " Locale=" + locale +
> "";
> +    }
> +
>      public static String getMockString(String id, String entry, Locale
> locale) throws MessageNotFoundException {
> -        return "Id=" + id + " Entry=" + entry + " Locale=" + locale + "";
> +        return getMockString("mock", id, entry, locale);
>      }
> 
> +    public static String getFormattedMockString(String providerId, String
> id, String entry, String[] arguments, Locale locale) {
> +        return MessageFormat.format(getMockString(providerId, id, entry,
> locale), arguments);
> +    }
> +
>      public static String getFormattedMockString(String id, String entry,
> String[] arguments, Locale locale) {
>          return MessageFormat.format(getMockString(id, entry, locale),
> arguments);
>      }
> Index: src/test/org/apache/commons/i18n/MessageManagerTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/MessageManagerTest.java	(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/MessageManagerTest.java	(working
> copy)
> @@ -55,26 +55,48 @@
> 
>          addMockProvider(); // Add mock provider
> 
> -        assertEquals("Throwing mock not used", "Id=dummyId
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Throwing mock not used", "Source=mock Id=dummyId
> Entry=dummyEntry Locale=en_US",
>                  MessageManager.getText("dummyId", "dummyEntry", null,
> Locale.US, "defaultText"));
> 
>          removeThrowingMockProvider(); // Removing throwing mock and keep
> only normal mock
> 
> -        assertEquals("Default text not used", "Id=dummyId
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Default text not used", "Source=mock Id=dummyId
> Entry=dummyEntry Locale=en_US",
>                  MessageManager.getText("dummyId", "dummyEntry", null,
> Locale.US, "defaultText"));
> 
> -        assertEquals("Normal lookup", "Id=id Entry=entry Locale=en_US",
> +        assertEquals("Normal lookup", "Source=mock Id=id Entry=entry
> Locale=en_US",
>                  MessageManager.getText("id", "entry", null, Locale.US));
>          assertEquals("Single argument",
> -                "Id=id Entry=entry value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
>                  MessageManager.getText("id", "entry {0}", new String[]
> {"value1"}, Locale.US));
>          assertEquals("Multiple arguments",
> -                "Id=id Entry=entry value0: value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value0: value1
> Locale=en_US",
>                  MessageManager.getText("id", "entry {0}: {1}", new
> String[] {"value0", "value1"},Locale.US));
> 
>          assertEquals("Single argument and default",
> -                "Id=id Entry=entry value1 Locale=en_US",
> +                "Source=mock Id=id Entry=entry value1 Locale=en_US",
>                  MessageManager.getText("id", "entry {0}", new String[]
> {"value1"},Locale.US, "defaultText"));
> +
> +        // Named provider not found
> +        try {
> +            MessageManager.getText("mockProvider2", "dummyId",
> "dummyEntry", null, Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'mockProvider2' not
> installed", mnfex.getMessage());
> +        }
> +
> +        assertEquals("Default text used", "defaultText",
> +                MessageManager.getText("mockProvider2", "dummyId",
> "dummyEntry", null, Locale.US, "defaultText"));
> +
> +
> +        // Named provider found
> +        addMockProvider("mockProvider2");
> +
> +        assertEquals("Default text not used, qualified lookup",
> "Source=mockProvider2 Id=dummyId Entry=dummyEntry Locale=en_US",
> +                MessageManager.getText("mockProvider2", "dummyId",
> "dummyEntry", null, Locale.US, "defaultText"));
> +
> +        assertEquals("Normal qualified lookup", "Source=mockProvider2
> Id=id Entry=entry Locale=en_US",
> +                MessageManager.getText("mockProvider2", "id", "entry",
> null, Locale.US));
>      }
> 
>      public void testGetEntries() {
> @@ -100,8 +122,8 @@
> 
>          Map entries = MessageManager.getEntries("dummyId", Locale.US);
>          assertEquals("No of entries", 2, entries.size());
> -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1
> Locale=en_US", entries.get("entry1"));
> -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2
> Locale=en_US", entries.get("entry2"));
> +        assertEquals("Entry 1 match", "Source=mock Id=dummyId
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mock Id=dummyId
> Entry=entry2 Locale=en_US", entries.get("entry2"));
> 
>          removeThrowingMockProvider(); // Removing throwing mock and keep
> only normal mock
> 
> @@ -109,7 +131,24 @@
> 
>          entries = MessageManager.getEntries("dummyId", Locale.US);
>          assertEquals("No of entries", 2, entries.size());
> -        assertEquals("Entry 1 match", "Id=dummyId Entry=entry1
> Locale=en_US", entries.get("entry1"));
> -        assertEquals("Entry 2 match", "Id=dummyId Entry=entry2
> Locale=en_US", entries.get("entry2"));
> +        assertEquals("Entry 1 match", "Source=mock Id=dummyId
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mock Id=dummyId
> Entry=entry2 Locale=en_US", entries.get("entry2"));
> +
> +        // Named provider not found
> +        try {
> +            MessageManager.getEntries("mockProvider2", "dummyId",
> Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'mockProvider2' not
> installed", mnfex.getMessage());
> +        }
> +
> +        // Named provider found
> +        addMockProvider("mockProvider2");
> +
> +        entries = MessageManager.getEntries("mockProvider2", "dummyId",
> Locale.US);
> +        assertEquals("No of entries", 2, entries.size());
> +        assertEquals("Entry 1 match", "Source=mockProvider2 Id=dummyId
> Entry=entry1 Locale=en_US", entries.get("entry1"));
> +        assertEquals("Entry 2 match", "Source=mockProvider2 Id=dummyId
> Entry=entry2 Locale=en_US", entries.get("entry2"));
>      }
>  }
> \ No newline at end of file
> Index: src/test/org/apache/commons/i18n/LocalizedBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/LocalizedBundleTest.java	(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/LocalizedBundleTest.java	(working
> copy)
> @@ -24,21 +24,38 @@
>  public class LocalizedBundleTest extends MockProviderTestBase {
>      public void testConstructors() {
>          LocalizedBundle lb = new LocalizedBundle("dummyId1");
> +        assertNull("No provider", lb.getProviderId());
>          assertEquals("Id set", "dummyId1", lb.getId());
>          assertNotNull("Arguments not null", lb.getArguments());
>          assertEquals("No arguments", 0, lb.getArguments().length);
> 
> +        LocalizedBundle lbProvider = new
> LocalizedBundle("dummyProvider2", "dummyId2");
> +        assertEquals("Provider set", "dummyProvider2",
> lbProvider.getProviderId());
> +        assertEquals("Id set", "dummyId2", lbProvider.getId());
> +        assertNotNull("Arguments not null", lbProvider.getArguments());
> +        assertEquals("No arguments", 0,
> lbProvider.getArguments().length);
> +
>          String[] arguments = new String[]{"arg1", "arg2"};
> -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2",
> arguments);
> -        assertEquals("Id set", "dummyId2", lbArgs.getId());
> +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3",
> arguments);
> +        assertNull("No provider", lbArgs.getProviderId());
> +        assertEquals("Id set", "dummyId3", lbArgs.getId());
>          assertNotNull("Arguments not null", lbArgs.getArguments());
>          assertEquals("No of arguments", 2, lbArgs.getArguments().length);
>          assertEquals("Arguments", arguments, lbArgs.getArguments());
> +
> +        LocalizedBundle lbProviderArgs = new
> LocalizedBundle("dummyProvider4", "dummyId4", arguments);
> +        assertEquals("Provider set", "dummyProvider4",
> lbProviderArgs.getProviderId());
> +        assertEquals("Id set", "dummyId4", lbProviderArgs.getId());
> +        assertNotNull("Arguments not null",
> lbProviderArgs.getArguments());
> +        assertEquals("No of arguments", 2,
> lbProviderArgs.getArguments().length);
> +        assertEquals("Arguments", arguments,
> lbProviderArgs.getArguments());
>      }
> 
>      public void testGetEntry() {
>          LocalizedBundle lb = new LocalizedBundle("dummyId1");
> -        LocalizedBundle lbArgs = new LocalizedBundle("dummyId2", new
> String[] {"arg1", "arg2"});
> +        LocalizedBundle lbProvider = new
> LocalizedBundle("dummyProvider2", "dummyId2");
> +        LocalizedBundle lbArgs = new LocalizedBundle("dummyId3", new
> String[] {"arg1", "arg2"});
> +        LocalizedBundle lbProviderArgs = new
> LocalizedBundle("dummyProvider4", "dummyId4", new String[] {"arg1",
> "arg2"});
> 
>          // Test errors
>          try {
> @@ -63,15 +80,53 @@
> 
>          addMockProvider(); // Add mock provider
> 
> -        assertEquals("Default text not used", "Id=dummyId1
> Entry=dummyEntry Locale=en_US",
> +        assertEquals("Default text not used", getMockString("dummyId1",
> "dummyEntry", Locale.US),
>                  lb.getEntry("dummyEntry", Locale.US, "defaltText"));
> 
> -        assertEquals("Normal lookup", "Id=dummyId1 Entry=entry
> Locale=en_US", lb.getEntry("entry", Locale.US));
> -        assertEquals("Arguments missing", "Id=dummyId1 Entry=entry {0}
> Locale=en_US",
> +        assertEquals("Normal lookup", getMockString("dummyId1", "entry",
> Locale.US), lb.getEntry("entry", Locale.US));
> +        assertEquals("Arguments missing", "Source=mock Id=dummyId1
> Entry=entry {0} Locale=en_US",
>                  lb.getEntry("entry {0}", Locale.US));
> -        assertEquals("Argument", "Id=dummyId2 Entry=entry arg1 arg2
> Locale=en_US",
> +        assertEquals("Argument", "Source=mock Id=dummyId3 Entry=entry
> arg1 arg2 Locale=en_US",
>                  lbArgs.getEntry("entry {0} {1}", Locale.US));
> -        assertEquals("Arguments and default", "Id=dummyId2 Entry=entry
> arg1 arg2 Locale=en_US",
> +        assertEquals("Arguments and default", "Source=mock Id=dummyId3
> Entry=entry arg1 arg2 Locale=en_US",
>                  lbArgs.getEntry("entry {0} {1}", Locale.US,
> "defaultText"));
> +
> +        // Named provider not found
> +        try {
> +            lbProvider.getEntry("dummyEntry", Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'dummyProvider2' not
> installed", mnfex.getMessage());
> +        }
> +
> +        try {
> +            lbProviderArgs.getEntry("dummyEntry", Locale.US);
> +            fail("Unknown provider should throw Exception");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Error text", "Provider 'dummyProvider4' not
> installed", mnfex.getMessage());
> +        }
> +
> +        assertEquals("Default text", "defaultText",
> lbProvider.getEntry("dummyEntry", Locale.US, "defaultText"));
> +        assertEquals("Default text", "defaultText",
> lbProviderArgs.getEntry("dummyEntry", Locale.US, "defaultText"));
> +
> +        // Named provider found
> +        addMockProvider("dummyProvider2");
> +        addMockProvider("dummyProvider4");
> +
> +        assertEquals("Named provider: Default text not used",
> +                getMockString("dummyProvider2", "dummyId2", "dummyEntry",
> Locale.US),
> +                lbProvider.getEntry("dummyEntry", Locale.US,
> "defaltText"));
> +
> +        assertEquals("Named provider: Normal lookup",
> getMockString("dummyProvider2", "dummyId2", "entry", Locale.US),
> +                lbProvider.getEntry("entry", Locale.US));
> +        assertEquals("Named provider: Arguments missing",
> "Source=dummyProvider2 Id=dummyId2 Entry=entry {0} Locale=en_US",
> +                lbProvider.getEntry("entry {0}", Locale.US));
> +        assertEquals("Named provider: Argument", "Source=dummyProvider4
> Id=dummyId4 Entry=entry arg1 arg2 Locale=en_US",
> +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US));
> +        assertEquals("Named provider: Arguments and default",
> +                "Source=dummyProvider4 Id=dummyId4 Entry=entry arg1 arg2
> Locale=en_US",
> +                lbProviderArgs.getEntry("entry {0} {1}", Locale.US,
> "defaultText"));
>      }
>  }
> Index: src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/XMLMessageProviderTest.java
(working
> copy)
> @@ -2,7 +2,7 @@
>  *
>  * ====================================================================
>  *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
> @@ -56,12 +56,12 @@
>          }
> 
>          XMLMessageProvider.install("org.apache.commons-i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> 
>          assertEquals("Hallo Welt", testMessage.getTitle(Locale.GERMAN));
> 
>          XMLMessageProvider.update("org.apache.commons-i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> 
>          assertEquals("OK after update", "Hallo Welt",
> testMessage.getTitle(Locale.GERMAN));
> 
> @@ -77,14 +77,14 @@
> 
>          // Try to parse non-XML file
>          XMLMessageProvider.install("org.apache.commons-i18n.error",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messag
> eBundle.properties"));
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("messag
> eBundle.properties"));
>      }
> -
> +
>      public void testGetText() {
>  //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> -//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> +//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
>          XMLMessageProvider xmlmp = new
> XMLMessageProvider("org.apache.commons-i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> 
>          assertEquals("Default locale", "hello world",
> xmlmp.getText("helloWorld", "title", Locale.US));
>          assertEquals("Default locale", "hello world",
> xmlmp.getText("helloWorld", "title", Locale.UK));
> @@ -123,9 +123,9 @@
> 
>      public void testGetTextVariants() {
>  //        XMLMessageProvider.install("org.apache.commons-i18n.variants",
> -//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> +//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
>          XMLMessageProvider xmlmp = new
> XMLMessageProvider("org.apache.commons-i18n.variants",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("varian
> tTestMessages.xml"));
> 
>          assertEquals("hello world", xmlmp.getText("variants", "theKey",
> Locale.ENGLISH));
>          assertEquals("Botswana", "Hello Botswana",
> xmlmp.getText("variants", "theKey", new Locale("", "BW")));
> @@ -135,9 +135,9 @@
> 
>      public void testGetEntries() {
>  //        XMLMessageProvider.install("org.apache.commons-i18n.test",
> -//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
> +//
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml"));
>          Map usEntries = new XMLMessageProvider("org.apache.commons-
> i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
>                      getEntries("helloWorld", Locale.US);
>          assertEquals("Default locale, no of entries", 5,
> usEntries.size());
>          assertEquals("Default locale, titel", "hello world",
> usEntries.get("title"));
> @@ -151,7 +151,7 @@
>          assertEquals("This entry is not translated to any other languages
> (XML)", usEntries.get("notTranslated"));
> 
>          Map germanEntries = new XMLMessageProvider("org.apache.commons-
> i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
>                      getEntries("helloWorld", Locale.GERMAN);
>          assertEquals("No of entries", 4, germanEntries.size());
>          assertEquals("Hallo Welt", germanEntries.get("title"));
> @@ -163,7 +163,7 @@
>  //        assertEquals("This entry is not translated to any other
> languages", germanEntries.get("notTranslated"));
> 
>          Map japaneseEntries = new XMLMessageProvider("org.apache.commons-
> i18n.test",
> -
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
> +
> Thread.currentThread().getContextClassLoader().getResourceAsStream("testMe
> ssages.xml")).
>                      getEntries("helloWorld", Locale.JAPANESE);
>          assertEquals("Fallback locale, no of entries", 5,
> japaneseEntries.size());
> 
> Index:
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> ===================================================================
> ---
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> 	(revision 170884)
> +++
> src/test/org/apache/commons/i18n/ResourceBundleMessageProviderTest.java
> 	(working copy)
> @@ -2,7 +2,7 @@
>  *
>  * ====================================================================
>  *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
> @@ -45,7 +45,7 @@
>          ResourceBundleMessageProvider.uninstall("messageBundle");
>          ResourceBundleMessageProvider.uninstall("messageBundle2");
>          ResourceBundleMessageProvider.uninstall("nonExistentBundle");
> -
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListRes
> ourceBundle");
> +
> ResourceBundleMessageProvider.uninstall("org.apache.commons.i18n.MyListRes
> ourceBundle");
>      }
> 
>      public void testInstallResourceBundle() {
> @@ -89,17 +89,11 @@
> 
>          // Test with list resource bundle
>  //        ResourceBundleMessageProvider.uninstall("messageBundle"); //
> Remove
> -//
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResou
> rceBundle"); // Install ListResourceBundle
> +//
> ResourceBundleMessageProvider.install("org.apache.commons.i18n.MyListResou
> rceBundle"); // Install ListResourceBundle
>          ResourceBundleMessageProvider listResourceBundleProvider =
>                  new
> ResourceBundleMessageProvider("org.apache.commons.i18n.MyListResourceBundl
> e"); // Install ListResourceBundle
>          assertEquals("Value from ListResourceBundle",
> "listResourceValue", listResourceBundleProvider.getText("helloWorld",
> "title", Locale.US));
> -        try {
> -            String s = listResourceBundleProvider.getText("helloWorld",
> "text", Locale.US);
> -            fail("Entry should not be found, since it is numeric. Found
> text: " + s);
> -        }
> -        catch(MessageNotFoundException mnfex) {
> -            assertEquals("No message entries found for bundle with key
> helloWorld", mnfex.getMessage());
> -        }
> +        assertEquals("Value from ListResourceBundle", "1",
> listResourceBundleProvider.getText("helloWorld", "text", Locale.US));
> 
>          try {
>              rbmp.getText("nonExistentId", "nonExistentEntry", Locale.US);
> Index: src/test/org/apache/commons/i18n/I18nTestSuite.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/I18nTestSuite.java	(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/I18nTestSuite.java	(working
copy)
> @@ -2,7 +2,7 @@
>  *
>  * ====================================================================
>  *
> -* Copyright 2004 The Apache Software Foundation
> +* Copyright 2004 The Apache Software Foundation
>  *
>  * Licensed under the Apache License, Version 2.0 (the "License");
>  * you may not use this file except in compliance with the License.
> Index: src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> 	(revision 170884)
> +++ src/test/org/apache/commons/i18n/bundles/ErrorBundleTest.java
> 	(working copy)
> @@ -52,6 +52,38 @@
>                  eb.getDetails(Locale.US, "defaultText"));
>      }
> 
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId");
> +        try {
> +            eb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText", eb.getText(Locale.US,
> "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", ErrorBundle.TEXT, Locale.US),
> +                eb.getText(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", ErrorBundle.TITLE, Locale.US),
> +                eb.getTitle(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", ErrorBundle.SUMMARY, Locale.US),
> +                eb.getSummary(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", ErrorBundle.DETAILS, Locale.US),
> +                eb.getDetails(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", ErrorBundle.TEXT, Locale.US),
> +                eb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", ErrorBundle.TITLE, Locale.US),
> +                eb.getTitle(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", ErrorBundle.SUMMARY, Locale.US),
> +                eb.getSummary(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", ErrorBundle.DETAILS, Locale.US),
> +                eb.getDetails(Locale.US, "defaultText"));
> +    }
> +
>      public void testWithArguments() {
>          String[] arguments = new String[]{"arg1", "arg2"};
>          ErrorBundle eb = new ErrorBundle("dummyId", arguments);
> @@ -83,4 +115,45 @@
>          assertEquals("Default not used",
> getFormattedMockString("dummyId", ErrorBundle.DETAILS, arguments,
> Locale.US),
>                  eb.getDetails(Locale.US, "defaultText"));
>      }
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        ErrorBundle eb = new ErrorBundle("dummyProvider", "dummyId",
> arguments);
> +        try {
> +            eb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2",
> eb.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.TEXT, arguments, Locale.US),
> +                eb.getText(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.TITLE, arguments, Locale.US),
> +                eb.getTitle(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.SUMMARY, arguments, Locale.US),
> +                eb.getSummary(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.DETAILS, arguments, Locale.US),
> +                eb.getDetails(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.TEXT, arguments, Locale.US),
> +                eb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.TITLE, arguments, Locale.US),
> +                eb.getTitle(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.SUMMARY, arguments, Locale.US),
> +                eb.getSummary(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> ErrorBundle.DETAILS, arguments, Locale.US),
> +                eb.getDetails(Locale.US, "defaultText"));
> +    }
>  }
> \ No newline at end of file
> Index: src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> 	(revision 170884)
> +++ src/test/org/apache/commons/i18n/bundles/MessageBundleTest.java
> 	(working copy)
> @@ -46,6 +46,30 @@
>                  mb.getTitle(Locale.US, "defaultText"));
>      }
> 
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId");
> +        try {
> +            mb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText", mb.getText(Locale.US,
> "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", MessageBundle.TEXT, Locale.US),
> +                mb.getText(Locale.US));
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", MessageBundle.TITLE, Locale.US),
> +                mb.getTitle(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", MessageBundle.TEXT, Locale.US),
> +                mb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", MessageBundle.TITLE, Locale.US),
> +                mb.getTitle(Locale.US, "defaultText"));
> +    }
> +
>      public void testWithArguments() {
>          String[] arguments = new String[]{"arg1", "arg2"};
>          MessageBundle mb = new MessageBundle("dummyId", arguments);
> @@ -69,4 +93,33 @@
>          assertEquals("Default not used",
> getFormattedMockString("dummyId", MessageBundle.TITLE, arguments,
> Locale.US),
>                  mb.getTitle(Locale.US, "defaultText"));
>      }
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        MessageBundle mb = new MessageBundle("dummyProvider", "dummyId",
> arguments);
> +        try {
> +            mb.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2",
> mb.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> MessageBundle.TEXT, arguments, Locale.US),
> +                mb.getText(Locale.US));
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> MessageBundle.TITLE, arguments, Locale.US),
> +                mb.getTitle(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> MessageBundle.TEXT, arguments, Locale.US),
> +                mb.getText(Locale.US, "defaultText"));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> MessageBundle.TITLE, arguments, Locale.US),
> +                mb.getTitle(Locale.US, "defaultText"));
> +    }
>  }
> Index: src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
> ===================================================================
> --- src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
(revision
> 170884)
> +++ src/test/org/apache/commons/i18n/bundles/TextBundleTest.java
(working
> copy)
> @@ -43,6 +43,26 @@
>                  textBundle.getText(Locale.US, "defaultText"));
>      }
> 
> +    public void testWithProvider() {
> +        addMockProvider(); // Add wrong provider
> +        TextBundle textBundle = new TextBundle("dummyProvider",
> "dummyId");
> +        try {
> +            textBundle.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText",
> textBundle.getText(Locale.US, "defaultText"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use", getMockString("dummyProvider",
> "dummyId", TextBundle.TEXT, Locale.US),
> +                textBundle.getText(Locale.US));
> +        assertEquals("Default not used", getMockString("dummyProvider",
> "dummyId", TextBundle.TEXT, Locale.US),
> +                textBundle.getText(Locale.US, "defaultText"));
> +    }
> +
>      public void testWithArguments() {
>          String[] arguments = new String[]{"arg1", "arg2"};
>          TextBundle textBundle = new TextBundle("dummyId", arguments);
> @@ -62,4 +82,26 @@
>          assertEquals("Default not used",
> getFormattedMockString("dummyId", TextBundle.TEXT, arguments, Locale.US),
>                  textBundle.getText(Locale.US, "defaultText"));
>      }
> -}
> +
> +    public void testWithProviderAndArguments() {
> +        addMockProvider(); // Add wrong provider
> +        String[] arguments = new String[]{"arg1", "arg2"};
> +        TextBundle textBundle = new TextBundle("dummyProvider",
> "dummyId", arguments);
> +        try {
> +            textBundle.getText(Locale.US);
> +            fail("Entry not found should cause error");
> +        }
> +        catch(MessageNotFoundException mnfex) {
> +            assertEquals("Provider 'dummyProvider' not installed",
> mnfex.getMessage());
> +        }
> +        assertEquals("Default used", "defaultText arg1 arg2",
> textBundle.getText(Locale.US, "defaultText {0} {1}"));
> +
> +        addMockProvider("dummyProvider");
> +
> +        assertEquals("Normal use",
> +                getFormattedMockString("dummyProvider", "dummyId",
> TextBundle.TEXT, arguments, Locale.US),
> +                textBundle.getText(Locale.US));
> +        assertEquals("Default not used",
> +                getFormattedMockString("dummyProvider", "dummyId",
> TextBundle.TEXT, arguments, Locale.US),
> +                textBundle.getText(Locale.US, "defaultText"));
> +    }}
> Index: src/java/org/apache/commons/i18n/MessageManager.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/MessageManager.java	(revision
> 170884)
> +++ src/java/org/apache/commons/i18n/MessageManager.java	(working
copy)
> @@ -74,6 +74,14 @@
>      }
> 
>      /**
> +     * Remove all <code>{@link MessageProvider}</code>s from the
> +     * <code>MessageManager</code>. Used for tearing down unit tests.
> +     */
> +    static void clearMessageProviders() {
> +        messageProviders.clear();
> +    }
> +
> +    /**
>       * Remove custom <code>{@link MessageProvider}</code> from the
>       * <code>MessageManager</code>. Used for tearing down unit tests.
>       *
> @@ -82,6 +90,7 @@
>      static void removeMessageProvider(String providerId) {
>          messageProviders.remove(providerId);
>      }
> +
>      /**
>       * Iterates over all registered message providers in order to find
> the given
>       * entry in the requested message bundle.
> @@ -149,6 +158,64 @@
>      }
> 
>      /**
> +     * Tries to find the desired entry in the named message provider.
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param id
> +     *            The identifier that will be used to retrieve the
> message
> +     *            bundle
> +     * @param entry
> +     *            The desired message entry
> +     * @param arguments
> +     *            The dynamic parts of the message that will be evaluated
> using
> +     *            the standard java text formatting abilities.
> +     * @param locale
> +     *            The locale in which the message will be printed
> +     * @exception MessageNotFoundException
> +     *                Will be thrown if the requested message provider
> cannot be found or
> +     *                no message bundle can be found for the given id or
> if the desired
> +     *                message entry is missing in the retrieved bundle
> +     * @return The localized text
> +     */
> +    public static String getText(String providerId, String id, String
> entry, Object[] arguments,
> +            Locale locale) throws MessageNotFoundException {
> +        MessageProvider provider = (MessageProvider)
> messageProviders.get(providerId);
> +        if(provider == null)
> +            throw new MessageNotFoundException("Provider '" + providerId
> + "' not installed");
> +        String text = provider.getText(id, entry, locale);
> +        return MessageFormat.format(text, arguments);
> +    }
> +
> +    /**
> +     * Iterates over all registered message providers in order to find
> the given
> +     * entry in the requested message bundle.
> +     *
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param id
> +     *            The identifier that will be used to retrieve the
> message
> +     *            bundle
> +     * @param entry
> +     *            The desired message entry
> +     * @param arguments
> +     *            The dynamic parts of the message that will be evaluated
> using
> +     *            the standard java text formatting abilities.
> +     * @param locale
> +     *            The locale in which the message will be printed
> +     * @param defaultText
> +     *            If no message bundle or message entry could be found
> for the
> +     *            specified parameters, the default text will be
> returned.
> +     * @return The localized text or the default text if the message
> could not
> +     *         be found
> +     */
> +    public static String getText(String providerId, String id, String
> entry, Object[] arguments,
> +            Locale locale, String defaultText) {
> +        try {
> +            return getText(providerId, id, entry, arguments, locale);
> +        } catch (MessageNotFoundException e) {
> +            return MessageFormat.format(defaultText, arguments);
> +        }
> +    }
> +
> +    /**
>       * Returns a map containing all available message entries for the
> given
>       * locale. The map contains keys of type {@link String}containing the
> keys
>       * of the available message entries and values of type {@link String}
> @@ -168,4 +235,18 @@
>          }
>          throw exception;
>      }
> +
> +  /**
> +   * Returns a map containing all available message entries for the given
> +   * locale. The map contains keys of type {@link String}containing the
> keys
> +   * of the available message entries and values of type {@link String}
> +   * containing the localized message entries.
> +   */
> +  public static Map getEntries(String providerId, String id, Locale
> locale)
> +          throws MessageNotFoundException {
> +      MessageProvider provider = (MessageProvider)
> messageProviders.get(providerId);
> +      if(provider == null)
> +          throw new MessageNotFoundException("Provider '" + providerId +
> "' not installed");
> +      return provider.getEntries(id, locale);
> +  }
>  }
> \ No newline at end of file
> Index: src/java/org/apache/commons/i18n/LocalizedBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/LocalizedBundle.java	(revision
> 170884)
> +++ src/java/org/apache/commons/i18n/LocalizedBundle.java	(working
copy)
> @@ -42,16 +42,25 @@
>  public class LocalizedBundle implements Serializable {
>      public final static String ID = "id";
> 
> +    protected String providerId;
>      protected String id;
>      protected Object[] arguments;
> 
> +  /**
> +   * @param providerId The name of the message provider (i.e. source) to
> use for the message
> +   * @param messageId The messageId refers the corresponding bundle in
> the file containing
> +   * the localized messages.
> +   */
> +  public LocalizedBundle(String providerId, String messageId) {
> +      this(providerId, messageId, new Object[0]);
> +  }
> +
>      /**
>       * @param messageId The messageId refers the corresponding bundle in
> the file containing
>       * the localized messages.
>       */
>      public LocalizedBundle(String messageId) {
> -        this.id = messageId;
> -        this.arguments = new Object[0];
> +        this(messageId, new Object[0]);
>      }
> 
>      /**
> @@ -65,6 +74,19 @@
>          this.arguments = arguments;
>      }
> 
> +  /**
> +   * @param providerId The name of the message provider (i.e. source) to
> use for the message
> +   * @param messageId The messageId refers the corresponding bundle in
> the file containing
> +   * the localized messages.
> +   * @param arguments An array of objects containing arguments for the
> messages. These arguments
> +   * are used to insert dynamic values into the localized messages.
> +   */
> +  public LocalizedBundle(String providerId, String messageId, Object[]
> arguments) {
> +    this.providerId = providerId;
> +    this.id = messageId;
> +      this.arguments = arguments;
> +  }
> +
>      /**
>       * @return returns the id of this bundle
>       */
> @@ -78,8 +100,15 @@
>      public Object[] getArguments() {
>      	return arguments;
>      }
> -
> +
>      /**
> +     * @return The name of the message provider (i.e. source) to use for
> the message
> +     */
> +    public String getProviderId() {
> +        return providerId;
> +    }
> +
> +    /**
>       * @param key the key of the specific message entry in the message
> bundle
>       * @param locale the locale for that this message should be rendered
>       * @return returns the text of the desired message entry for the
> given locale
> @@ -87,7 +116,9 @@
>       * in this bundle
>       */
>      public String getEntry(String key, Locale locale) throws
> MessageNotFoundException {
> -        return MessageManager.getText(id, key, arguments, locale);
> +        return providerId != null ?
> +            MessageManager.getText(providerId, id, key, arguments,
> locale) :
> +            MessageManager.getText(id, key, arguments, locale);
>      }
> 
>      /**
> @@ -97,6 +128,8 @@
>       * @return returns the text of the desired message entry for the
> given locale
>       */
>      public String getEntry(String key, Locale locale, String defaultText)
> {
> -        return MessageManager.getText(id, key, arguments, locale,
> defaultText);
> +        return providerId != null ?
> +            MessageManager.getText(providerId, id, key, arguments,
> locale, defaultText) :
> +            MessageManager.getText(id, key, arguments, locale,
> defaultText);
>      }
>  }
> \ No newline at end of file
> Index: src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> 	(revision 170884)
> +++ src/java/org/apache/commons/i18n/ResourceBundleMessageProvider.java
> 	(working copy)
> @@ -47,12 +47,9 @@
>       * @see
> org.apache.commons.i18n.MessageProvider#getText(java.lang.String,
> java.lang.String, java.util.Locale)
>       */
>      public String getText(String id, String entry, Locale locale) throws
> MessageNotFoundException {
> -        // TODO: Revise try/catch
>          try {
>              ResourceBundle resourceBundle =
> ResourceBundle.getBundle(baseName, locale);
> -             return resourceBundle.getString(id+"."+entry);
> -        } catch ( ClassCastException e ) {
> -            // ignore all entries that are not of type String
> +             return resourceBundle.getObject(id+"."+entry).toString();
>          }
>          catch ( MissingResourceException e ) {
>              logger.log(
> Index: src/java/org/apache/commons/i18n/bundles/ErrorBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/ErrorBundle.java	(revision
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/ErrorBundle.java	(working
> copy)
> @@ -45,6 +45,14 @@
>      }
> 
>      /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public ErrorBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>       * @param messageId Unique message id that identifies the message
>       * @param arguments An array of objects conaining the values that
> should be
>       * inserted into the localized message.
> @@ -54,6 +62,16 @@
>      }
> 
>      /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that
> should be
> +     * inserted into the localized message.
> +     */
> +    public ErrorBundle(String providerId, String messageId, Object[]
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
> +
> +    /**
>       * @param locale The locale that is used to find the appropriate
> localized text
>       * @return returns the localized message entry with the key
> <code>summary</code>
>       * @throws MessageNotFoundException is thrown if no entry with key
> <code>summary</code> could be found in the message bundle identified by
> the given message identifier
> Index: src/java/org/apache/commons/i18n/bundles/TextBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/TextBundle.java	(revision
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/TextBundle.java	(working
> copy)
> @@ -44,6 +44,14 @@
>      }
> 
>      /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public TextBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>       * @param messageId Unique message id that identifies the message
>       * @param arguments An array of objects conaining the values that
> should be
>       * inserted into the localized message.
> @@ -53,6 +61,16 @@
>      }
> 
>      /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that
> should be
> +     * inserted into the localized message.
> +     */
> +    public TextBundle(String providerId, String messageId, Object[]
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
> +
> +    /**
>       * @param locale The locale that is used to find the appropriate
> localized text
>       * @return returns the localized message entry with the key
> <code>text</code>
>       * @throws MessageNotFoundException is thrown if no entry with key
> <code>text</code> could be found in the message bundle identified by the
> given message identifier
> Index: src/java/org/apache/commons/i18n/bundles/MessageBundle.java
> ===================================================================
> --- src/java/org/apache/commons/i18n/bundles/MessageBundle.java
(revision
> 170884)
> +++ src/java/org/apache/commons/i18n/bundles/MessageBundle.java
(working
> copy)
> @@ -42,6 +42,14 @@
>      }
> 
>      /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     */
> +    public MessageBundle(String providerId, String messageId) {
> +        super(providerId, messageId);
> +    }
> +
> +    /**
>       * @param messageId Unique message id that identifies the message
>       * @param arguments An array of objects conaining the values that
> should be
>       * inserted into the localized message.
> @@ -50,6 +58,15 @@
>          super(messageId, arguments);
>      }
> 
> +    /**
> +     * @param providerId The name of the message provider (i.e. source)
> to use for the message
> +     * @param messageId Unique message id that identifies the message
> +     * @param arguments An array of objects conaining the values that
> should be
> +     * inserted into the localized message.
> +     */
> +    public MessageBundle(String providerId, String messageId, Object[]
> arguments) {
> +        super(providerId, messageId, arguments);
> +    }
> 
>      /**
>       * @param locale The locale that is used to find the appropriate
> localized text
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org