Make bundle R/W: improvement + unit tests
authorNiki Roo <niki@nikiroo.be>
Tue, 7 Mar 2017 17:01:22 +0000 (18:01 +0100)
committerNiki Roo <niki@nikiroo.be>
Tue, 7 Mar 2017 17:01:22 +0000 (18:01 +0100)
src/be/nikiroo/utils/resources/Bundle.java
src/be/nikiroo/utils/resources/TransBundle.java
src/be/nikiroo/utils/test/BundleTest.java
src/be/nikiroo/utils/test/TestLauncher.java

index b4019de53d67e851e096074021b8b7341b22eef8..4420109caa157a8358f1298b8186c71a05bec4c2 100644 (file)
@@ -52,7 +52,7 @@ public class Bundle<E extends Enum<E>> {
                this.type = type;
                this.name = name;
                this.changeMap = new HashMap<String, String>();
-               setBundle(name, Locale.getDefault());
+               setBundle(name, Locale.getDefault(), false);
        }
 
        /**
@@ -330,9 +330,14 @@ public class Bundle<E extends Enum<E>> {
 
        /**
         * Reload the {@link Bundle} data files.
+        * 
+        * @param resetToDefault
+        *            reset to the default configuration (do not look into the
+        *            possible user configuration files, only take the original
+        *            configuration)
         */
-       public void reload() {
-               setBundle(name, null);
+       public void reload(boolean resetToDefault) {
+               setBundle(name, null, resetToDefault);
        }
 
        /**
@@ -348,12 +353,15 @@ public class Bundle<E extends Enum<E>> {
                        return true;
                }
 
-               try {
-                       map.getObject(key);
-                       return true;
-               } catch (MissingResourceException e) {
-                       return false;
+               if (map != null) {
+                       try {
+                               map.getObject(key);
+                               return true;
+                       } catch (MissingResourceException e) {
+                       }
                }
+
+               return false;
        }
 
        /**
@@ -370,7 +378,7 @@ public class Bundle<E extends Enum<E>> {
                        return changeMap.get(key);
                }
 
-               if (containsKey(key)) {
+               if (map != null && containsKey(key)) {
                        return map.getString(key);
                }
 
@@ -536,13 +544,17 @@ public class Bundle<E extends Enum<E>> {
         *            the name of the bundle to load
         * @param locale
         *            the {@link Locale} to use
+        * @param resetToDefault
+        *            reset to the default configuration (do not look into the
+        *            possible user configuration files, only take the original
+        *            configuration)
         */
-       protected void setBundle(Enum<?> name, Locale locale) {
+       protected void setBundle(Enum<?> name, Locale locale, boolean resetToDefault) {
                map = null;
                changeMap.clear();
                String dir = Bundles.getDirectory();
 
-               if (dir != null) {
+               if (!resetToDefault && dir != null) {
                        try {
                                File file = getPropertyFile(dir, name.name(), locale);
                                if (file != null) {
@@ -556,8 +568,47 @@ public class Bundle<E extends Enum<E>> {
                }
 
                if (map == null) {
-                       map = ResourceBundle.getBundle(type.getPackage().getName() + "."
-                                       + name.name(), locale, new FixedResourceBundleControl());
+                       try {
+                               map = ResourceBundle.getBundle(type.getPackage().getName()
+                                               + "." + name.name(), locale,
+                                               new FixedResourceBundleControl());
+                       } catch (Exception e) {
+                               // We have no bundle for this Bundle
+                               map = null;
+                       }
+               }
+       }
+
+       /**
+        * Take a snapshot of the changes in memory in this {@link Bundle} made by
+        * the "set" methods ( {@link Bundle#setString(Enum, String)}...) at the
+        * current time.
+        * 
+        * @return a snapshot to use with {@link Bundle#restoreChanges(Object)}
+        */
+       protected Object takeChangesSnapshot() {
+               return new HashMap<String, String>(changeMap);
+       }
+
+       /**
+        * Restore a snapshot taken with {@link Bundle}, or reset the current
+        * changes if the snapshot is NULL.
+        * 
+        * @param snap
+        *            the snapshot or NULL
+        */
+       @SuppressWarnings("unchecked")
+       protected void restoreChanges(Object snap) {
+               if (snap == null) {
+                       changeMap.clear();
+               } else {
+                       if (snap instanceof Map) {
+                               changeMap = (Map<String, String>) snap;
+                       } else {
+                               throw new Error(
+                                               "Restoring changes in a Bundle must be done on a changes snapshot, "
+                                                               + "or NULL to discard current changes");
+                       }
                }
        }
 
index a3804401034692909302f04c50c39cdcad828e6d..125075a8bbd8268ca6c2310f2e3b40387132e2ac 100644 (file)
@@ -8,8 +8,6 @@ import java.util.List;
 import java.util.Locale;
 import java.util.regex.Pattern;
 
-import be.nikiroo.utils.resources.Bundles;
-
 /**
  * This class manages a translation-dedicated Bundle.
  * <p>
@@ -171,12 +169,12 @@ public class TransBundle<E extends Enum<E>> extends Bundle<E> {
        private void setLanguage(String language) {
                defaultLocale = (language == null || language.length() == 0);
                locale = getLocaleFor(language);
-               setBundle(name, locale);
+               setBundle(name, locale, false);
        }
 
        @Override
-       public void reload() {
-               setBundle(name, locale);
+       public void reload(boolean resetToDefault) {
+               setBundle(name, locale, resetToDefault);
        }
 
        @Override
@@ -199,16 +197,26 @@ public class TransBundle<E extends Enum<E>> extends Bundle<E> {
        @Override
        public void updateFile(String path) throws IOException {
                String prev = locale.getLanguage();
+               Object status = takeChangesSnapshot();
 
-               setLanguage(null); // default locale
+               // default locale
+               setLanguage(null);
+               if (prev.equals(getLocaleFor(null).getLanguage())) {
+                       // restore snapshot if default locale = current locale
+                       restoreChanges(status);
+               }
                super.updateFile(path);
 
                for (String lang : getKnownLanguages()) {
                        setLanguage(lang);
+                       if (lang.equals(prev)) {
+                               restoreChanges(status);
+                       }
                        super.updateFile(path);
                }
 
                setLanguage(prev);
+               restoreChanges(status);
        }
 
        @Override
index 119f3b9d6e496a305df52467ea0e9ff2650468f5..4b9ac7dd81ed2adec96876104bd0e960c99536c6 100644 (file)
@@ -1,6 +1,8 @@
 package be.nikiroo.utils.test;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
 
 import be.nikiroo.utils.IOUtils;
 import be.nikiroo.utils.resources.Bundle;
@@ -11,10 +13,6 @@ class BundleTest extends TestLauncher {
        private File tmp;
        private B b = new B();
 
-       protected boolean isMain() {
-               return true;
-       }
-
        public BundleTest(String[] args) {
                this("Bundle test", args);
        }
@@ -22,78 +20,175 @@ class BundleTest extends TestLauncher {
        protected BundleTest(String name, String[] args) {
                super(name, args);
 
-               addTests();
-
-               if (isMain()) {
-                       addSeries(new BundleTest("After saving/reloading the resources",
-                                       args) {
-                               @Override
-                               protected void start() throws Exception {
-                                       tmp = File.createTempFile("nikiroo-utils", ".test");
-                                       tmp.delete();
-                                       tmp.mkdir();
-                                       b.updateFile(tmp.getAbsolutePath());
-                                       Bundles.setDirectory(tmp.getAbsolutePath());
-                                       b.reload();
-                               }
+               for (TestCase test : getSimpleTests()) {
+                       addTest(test);
+               }
 
-                               @Override
-                               protected void stop() {
-                                       IOUtils.deltree(tmp);
+               addSeries(new TestLauncher("After saving/reloading the resources", args) {
+                       {
+                               for (TestCase test : getSimpleTests()) {
+                                       addTest(test);
                                }
+                       }
 
-                               @Override
-                               protected boolean isMain() {
-                                       return false;
-                               }
-                       });
-               }
+                       @Override
+                       protected void start() throws Exception {
+                               tmp = File.createTempFile("nikiroo-utils", ".test");
+                               tmp.delete();
+                               tmp.mkdir();
+                               b.updateFile(tmp.getAbsolutePath());
+                               Bundles.setDirectory(tmp.getAbsolutePath());
+                               b.reload(false);
+                       }
+
+                       @Override
+                       protected void stop() {
+                               IOUtils.deltree(tmp);
+                       }
+               });
+
+               addSeries(new TestLauncher("Read/Write support", args) {
+                       {
+                               addTest(new TestCase("Reload") {
+                                       @Override
+                                       public void test() throws Exception {
+                                               String now = b.getString(E.ONE);
+                                               b.reload(true);
+                                               String def = b.getString(E.ONE);
+                                               b.reload(false);
+
+                                               assertEquals("We should not have a bundle to load",
+                                                               null, def);
+                                               assertEquals("We should have reloaded the same files",
+                                                               now, b.getString(E.ONE));
+
+                                               // reset values for next tests
+                                               b.reload(false);
+                                       }
+                               });
+
+                               addTest(new TestCase("Set/Get") {
+                                       @Override
+                                       public void test() throws Exception {
+                                               String val = "Newp";
+                                               b.setString(E.ONE, val);
+                                               String setGet = b.getString(E.ONE);
+
+                                               assertEquals(val, setGet);
+
+                                               // reset values for next tests
+                                               b.restoreChanges(null);
+                                       }
+                               });
+
+                               addTest(new TestCase("Snapshots") {
+                                       @Override
+                                       public void test() throws Exception {
+                                               String val = "Newp";
+                                               String def = b.getString(E.ONE);
+
+                                               b.setString(E.ONE, val);
+                                               Object snap = b.takeChangesSnapshot();
+
+                                               b.restoreChanges(null);
+                                               assertEquals(
+                                                               "restoreChanges(null) should clear the changes",
+                                                               def, b.getString(E.ONE));
+                                               b.restoreChanges(snap);
+                                               assertEquals(
+                                                               "restoreChanges(snapshot) should restore the changes",
+                                                               val, b.getString(E.ONE));
+
+                                               // reset values for next tests
+                                               b.restoreChanges(null);
+                                       }
+                               });
+
+                               addTest(new TestCase("updateFile with changes") {
+                                       @Override
+                                       public void test() throws Exception {
+                                               String val = "Go to disk! (UTF-8 test: 日本語)";
+
+                                               String def = b.getString(E.ONE);
+                                               b.setString(E.ONE, val);
+                                               b.updateFile(tmp.getAbsolutePath());
+                                               b.reload(false);
+
+                                               assertEquals(val, b.getString(E.ONE));
+
+                                               // reset values for next tests
+                                               b.setString(E.ONE, def);
+                                               b.updateFile(tmp.getAbsolutePath());
+                                               b.reload(false);
+                                       }
+                               });
+                       }
+
+                       @Override
+                       protected void start() throws Exception {
+                               tmp = File.createTempFile("nikiroo-utils", ".test");
+                               tmp.delete();
+                               tmp.mkdir();
+                               b.updateFile(tmp.getAbsolutePath());
+                               Bundles.setDirectory(tmp.getAbsolutePath());
+                               b.reload(false);
+                       }
+
+                       @Override
+                       protected void stop() {
+                               IOUtils.deltree(tmp);
+                       }
+               });
        }
 
-       private void addTests() {
+       private List<TestCase> getSimpleTests() {
                String pre = "";
 
-               addTest(new TestCase(pre + "getString simple") {
+               List<TestCase> list = new ArrayList<TestCase>();
+
+               list.add(new TestCase(pre + "getString simple") {
                        @Override
                        public void test() throws Exception {
                                assertEquals("un", b.getString(E.ONE));
                        }
                });
 
-               addTest(new TestCase(pre + "getStringX with null suffix") {
+               list.add(new TestCase(pre + "getStringX with null suffix") {
                        @Override
                        public void test() throws Exception {
                                assertEquals("un", b.getStringX(E.ONE, null));
                        }
                });
 
-               addTest(new TestCase(pre + "getStringX with empty suffix") {
+               list.add(new TestCase(pre + "getStringX with empty suffix") {
                        @Override
                        public void test() throws Exception {
                                assertEquals(null, b.getStringX(E.ONE, ""));
                        }
                });
 
-               addTest(new TestCase(pre + "getStringX with existing suffix") {
+               list.add(new TestCase(pre + "getStringX with existing suffix") {
                        @Override
                        public void test() throws Exception {
                                assertEquals("un + suffix", b.getStringX(E.ONE, "suffix"));
                        }
                });
 
-               addTest(new TestCase(pre + "getStringX with not existing suffix") {
+               list.add(new TestCase(pre + "getStringX with not existing suffix") {
                        @Override
                        public void test() throws Exception {
                                assertEquals(null, b.getStringX(E.ONE, "fake"));
                        }
                });
 
-               addTest(new TestCase(pre + "getString with UTF-8 content") {
+               list.add(new TestCase(pre + "getString with UTF-8 content") {
                        @Override
                        public void test() throws Exception {
                                assertEquals("日本語 Nihongo", b.getString(E.JAPANESE));
                        }
                });
+
+               return list;
        }
 
        /**
@@ -106,6 +201,17 @@ class BundleTest extends TestLauncher {
                        super(E.class, N.bundle_test);
                }
 
+               @Override
+               // ...and make it public
+               public Object takeChangesSnapshot() {
+                       return super.takeChangesSnapshot();
+               }
+
+               @Override
+               // ...and make it public
+               public void restoreChanges(Object snap) {
+                       super.restoreChanges(snap);
+               }
        }
 
        /**
index 10a6e2794811036a12f21239d254f7dd3e2c483b..d01e0f802cf026f1aa886d6c99d2917538a67693 100644 (file)
@@ -20,7 +20,7 @@ public class TestLauncher {
        private class SetupException extends Exception {
                private static final long serialVersionUID = 1L;
 
-               public SetupException(Exception e) {
+               public SetupException(Throwable e) {
                        super(e);
                }
        }
@@ -33,7 +33,7 @@ public class TestLauncher {
        private class TearDownException extends Exception {
                private static final long serialVersionUID = 1L;
 
-               public TearDownException(Exception e) {
+               public TearDownException(Throwable e) {
                        super(e);
                }
        }
@@ -185,20 +185,20 @@ public class TestLauncher {
                for (TestCase test : tests) {
                        print(depth, test.getName());
 
-                       Exception ex = null;
+                       Throwable ex = null;
                        try {
                                try {
                                        test.setUp();
-                               } catch (Exception e) {
+                               } catch (Throwable e) {
                                        throw new SetupException(e);
                                }
                                test.test();
                                try {
                                        test.tearDown();
-                               } catch (Exception e) {
+                               } catch (Throwable e) {
                                        throw new TearDownException(e);
                                }
-                       } catch (Exception e) {
+                       } catch (Throwable e) {
                                ex = e;
                        }
 
@@ -300,7 +300,7 @@ public class TestLauncher {
         * @param error
         *            the {@link Exception} it ran into if any
         */
-       private void print(int depth, Exception error) {
+       private void print(int depth, Throwable error) {
                if (error != null) {
                        System.out.println(" " + koString);
                        StringWriter sw = new StringWriter();