fix library caching issues and change get-by-source, by-author.. into result-list
authorNiki Roo <niki@nikiroo.be>
Wed, 8 Apr 2020 12:27:39 +0000 (14:27 +0200)
committerNiki Roo <niki@nikiroo.be>
Wed, 8 Apr 2020 12:27:39 +0000 (14:27 +0200)
src/be/nikiroo/fanfix/library/BasicLibrary.java
src/be/nikiroo/fanfix/library/CacheLibrary.java
src/be/nikiroo/fanfix/library/LocalLibrary.java
src/be/nikiroo/fanfix/library/RemoteLibrary.java
src/be/nikiroo/fanfix/reader/cli/CliReader.java
src/be/nikiroo/fanfix/reader/tui/TuiReaderMainWindow.java
src/be/nikiroo/fanfix/reader/ui/GuiReaderBookInfo.java
src/be/nikiroo/fanfix/reader/ui/GuiReaderMainPanel.java
src/be/nikiroo/fanfix/test/LibraryTest.java

index c6ce22dd24c1c4fa85f60edfdcea7bd5f8de1b05..c2ab12b7b735d8349b51ea1beaaeab3ca7bac8e8 100644 (file)
@@ -149,7 +149,7 @@ abstract public class BasicLibrary {
                        return custom;
                }
 
-               List<MetaData> metas = getListBySource(source);
+               List<MetaData> metas = getList().filter(source, null, null);
                if (metas.size() > 0) {
                        return getCover(metas.get(0).getLuid());
                }
@@ -177,7 +177,7 @@ abstract public class BasicLibrary {
                        return custom;
                }
 
-               List<MetaData> metas = getListByAuthor(author);
+               List<MetaData> metas = getList().filter(null, author, null);
                if (metas.size() > 0) {
                        return getCover(metas.get(0).getLuid());
                }
@@ -338,7 +338,7 @@ abstract public class BasicLibrary {
         * @param pg
         *            the optional progress reporter
         */
-       public void refresh(Progress pg) {
+       public synchronized void refresh(Progress pg) {
                try {
                        getMetas(pg);
                } catch (IOException e) {
@@ -597,49 +597,8 @@ abstract public class BasicLibrary {
         * @throws IOException
         *             in case of IOException
         */
-       public synchronized List<MetaData> getList() throws IOException {
-               return getMetas(null);
-       }
-
-       /**
-        * List all the stories of the given source type in the {@link BasicLibrary} ,
-        * or all the stories if NULL is passed as a type.
-        * <p>
-        * Cover images not included.
-        * 
-        * @param source the type of story to retrieve, or NULL for all
-        * 
-        * @return the stories
-        * 
-        * @throws IOException in case of IOException
-        * 
-        * @deprecated use {@link BasicLibrary#getList(Progress)} and
-        *             {@link MetaResultList#filter(String, String, String)}
-        */
-       @Deprecated
-       public synchronized List<MetaData> getListBySource(String source) throws IOException {
-               return getList(null).filter(source, null, null);
-       }
-
-       /**
-        * List all the stories of the given author in the {@link BasicLibrary}, or
-        * all the stories if NULL is passed as an author.
-        * <p>
-        * Cover images not included.
-        * 
-        * @param author
-        *            the author of the stories to retrieve, or NULL for all
-        * 
-        * @return the stories
-        * 
-        * @throws IOException
-        *             in case of IOException
-        *             
-        *             @deprecated use {@link BasicLibrary#getList(Progress)} and
-        *             {@link MetaResultList#filter(String, String, String)}
-        */
-       public synchronized List<MetaData> getListByAuthor(String author) throws IOException {
-               return getList(null).filter(null, author, null);
+       public MetaResultList getList() throws IOException {
+               return getList(null);
        }
 
        /**
@@ -1058,8 +1017,6 @@ abstract public class BasicLibrary {
                meta.setTitle(newTitle);
                meta.setAuthor(newAuthor);
                saveMeta(meta, pg);
-
-               invalidateInfo(luid);
        }
 
        /**
index 9c83e62f76ceb388125cbc73d8769b296513b211..694f9ec267501d546ba8b44413cfeb346ef8963d 100644 (file)
@@ -5,6 +5,7 @@ import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.TreeSet;
 
 import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.bundles.UiConfig;
@@ -21,7 +22,8 @@ import be.nikiroo.utils.Progress;
  * @author niki
  */
 public class CacheLibrary extends BasicLibrary {
-       private List<MetaData> metas;
+       private List<MetaData> metasReal;
+       private List<MetaData> metasMixed;
        private BasicLibrary lib;
        private LocalLibrary cacheLib;
 
@@ -54,32 +56,37 @@ public class CacheLibrary extends BasicLibrary {
        }
 
        @Override
-       protected List<MetaData> getMetas(Progress pg) throws IOException {
+       protected synchronized List<MetaData> getMetas(Progress pg) throws IOException {
+               // We make sure that cached metas have precedence
+
                if (pg == null) {
                        pg = new Progress();
                }
 
-               if (metas == null) {
-                       metas = lib.getMetas(pg);
+               if (metasMixed == null) {
+                       if (metasReal == null) {
+                               metasReal = lib.getMetas(pg);
+                       }
+                       
+                       metasMixed = new ArrayList<MetaData>();
+                       TreeSet<String> cachedLuids = new TreeSet<String>();
+                       for (MetaData cachedMeta : cacheLib.getMetas(null)) {
+                               metasMixed.add(cachedMeta);
+                               cachedLuids.add(cachedMeta.getLuid());
+                       }
+                       for (MetaData realMeta : metasReal) {
+                               if (!cachedLuids.contains(realMeta.getLuid())) {
+                                       metasMixed.add(realMeta);
+                               }
+                       }
                }
 
                pg.done();
-               return new ArrayList<MetaData>(metas);
-       }
-
-       @Override
-       public synchronized MetaData getInfo(String luid) throws IOException {
-               MetaData info = cacheLib.getInfo(luid);
-               if (info == null) {
-                       info = lib.getInfo(luid);
-               }
-
-               return info;
+               return new ArrayList<MetaData>(metasMixed);
        }
 
        @Override
-       public synchronized Story getStory(String luid, MetaData meta, Progress pg)
-                       throws IOException {
+       public synchronized Story getStory(String luid, MetaData meta, Progress pg) throws IOException {
                if (pg == null) {
                        pg = new Progress();
                }
@@ -94,7 +101,7 @@ public class CacheLibrary extends BasicLibrary {
                if (!isCached(luid)) {
                        try {
                                cacheLib.imprt(lib, luid, pgImport);
-                               updateInfo(cacheLib.getInfo(luid));
+                               updateMetaCache(metasMixed, cacheLib.getInfo(luid));
                                pgImport.done();
                        } catch (IOException e) {
                                Instance.getInstance().getTraceHandler().error(e);
@@ -112,8 +119,7 @@ public class CacheLibrary extends BasicLibrary {
        }
 
        @Override
-       public synchronized File getFile(final String luid, Progress pg)
-                       throws IOException {
+       public synchronized File getFile(final String luid, Progress pg) throws IOException {
                if (pg == null) {
                        pg = new Progress();
                }
@@ -215,8 +221,29 @@ public class CacheLibrary extends BasicLibrary {
                cacheLib.setAuthorCover(author, getCover(luid));
        }
 
+       /**
+        * Invalidate the {@link Story} cache (when the content has changed, but we
+        * already have it) with the new given meta.
+        * <p>
+        * <b>Make sure to always use {@link MetaData} from the cached library 
+        * in priority, here.</b>
+        * 
+        * @param meta
+        *            the {@link Story} to clear from the cache
+        * 
+        * @throws IOException
+        *             in case of IOException
+        */
        @Override
+       @Deprecated
        protected void updateInfo(MetaData meta) throws IOException {
+               throw new IOException(
+                               "This method is not supported in a CacheLibrary, please use updateMetaCache");
+       }
+       
+       // relplace the meta in Metas by Meta, add it if needed
+       // return TRUE = added
+       private boolean updateMetaCache(List<MetaData> metas, MetaData meta) {
                if (meta != null && metas != null) {
                        boolean changed = false;
                        for (int i = 0; i < metas.size(); i++) {
@@ -228,32 +255,40 @@ public class CacheLibrary extends BasicLibrary {
 
                        if (!changed) {
                                metas.add(meta);
+                               return true;
                        }
                }
-
-               cacheLib.updateInfo(meta);
-               lib.updateInfo(meta);
+               
+               return false;
        }
 
        @Override
        protected void invalidateInfo(String luid) {
                if (luid == null) {
-                       metas = null;
-               } else if (metas != null) {
+                       metasReal = null;
+                       metasMixed = null;
+               } else {
+                       invalidateInfo(metasReal, luid);
+                       invalidateInfo(metasMixed, luid);
+               }
+
+               cacheLib.invalidateInfo(luid);
+               lib.invalidateInfo(luid);
+       }
+
+       // luid cannot be null
+       private void invalidateInfo(List<MetaData> metas, String luid) {
+               if (metas != null) {
                        for (int i = 0; i < metas.size(); i++) {
                                if (metas.get(i).getLuid().equals(luid)) {
                                        metas.remove(i--);
                                }
                        }
                }
-
-               cacheLib.invalidateInfo(luid);
-               lib.invalidateInfo(luid);
        }
 
        @Override
-       public synchronized Story save(Story story, String luid, Progress pg)
-                       throws IOException {
+       public synchronized Story save(Story story, String luid, Progress pg) throws IOException {
                Progress pgLib = new Progress();
                Progress pgCacheLib = new Progress();
 
@@ -266,9 +301,10 @@ public class CacheLibrary extends BasicLibrary {
                pg.addProgress(pgCacheLib, 1);
 
                story = lib.save(story, luid, pgLib);
+               updateMetaCache(metasReal, story.getMeta());
+               
                story = cacheLib.save(story, story.getMeta().getLuid(), pgCacheLib);
-
-               updateInfo(story.getMeta());
+               updateMetaCache(metasMixed, story.getMeta());
 
                return story;
        }
@@ -284,8 +320,8 @@ public class CacheLibrary extends BasicLibrary {
        }
 
        @Override
-       protected synchronized void changeSTA(String luid, String newSource,
-                       String newTitle, String newAuthor, Progress pg) throws IOException {
+       protected synchronized void changeSTA(String luid, String newSource, String newTitle, String newAuthor, Progress pg)
+                       throws IOException {
                if (pg == null) {
                        pg = new Progress();
                }
@@ -314,7 +350,12 @@ public class CacheLibrary extends BasicLibrary {
                meta.setAuthor(newAuthor);
                pg.done();
 
-               invalidateInfo(luid);
+               if (isCached(luid)) {
+                       updateMetaCache(metasMixed, meta);
+                       updateMetaCache(metasReal, lib.getInfo(luid));
+               } else {
+                       updateMetaCache(metasReal, meta);
+               }
        }
 
        @Override
@@ -334,7 +375,7 @@ public class CacheLibrary extends BasicLibrary {
        }
 
        @Override
-       public MetaData imprt(URL url, Progress pg) throws IOException {
+       public synchronized MetaData imprt(URL url, Progress pg) throws IOException {
                if (pg == null) {
                        pg = new Progress();
                }
@@ -346,10 +387,10 @@ public class CacheLibrary extends BasicLibrary {
                pg.addProgress(pgCache, 3);
 
                MetaData meta = lib.imprt(url, pgImprt);
-               updateInfo(meta);
-               
+               updateMetaCache(metasReal, meta);
+               metasMixed = null;
                clearFromCache(meta.getLuid());
-               
+
                pg.done();
                return meta;
        }
index c99a0fbebefc1a2fef30d6f83d8c0d080303b5ef..80d216b84c216fd32a5dc8cf26f9e4dc2a28353c 100644 (file)
@@ -98,7 +98,7 @@ public class LocalLibrary extends BasicLibrary {
        }
 
        @Override
-       protected List<MetaData> getMetas(Progress pg) {
+       protected synchronized List<MetaData> getMetas(Progress pg) {
                return new ArrayList<MetaData>(getStories(pg).keySet());
        }
 
@@ -214,7 +214,7 @@ public class LocalLibrary extends BasicLibrary {
                        }
                }
 
-               invalidateInfo();
+               updateInfo(meta);
        }
 
        @Override
index c2774f936e8966cb7358c30e446bd86f4242b027..65be7b1759e4893b2412f2c74cc00c0b3a95a2a7 100644 (file)
@@ -459,7 +459,7 @@ public class RemoteLibrary extends BasicLibrary {
        }
 
        @Override
-       protected List<MetaData> getMetas(Progress pg) throws IOException {
+       protected synchronized List<MetaData> getMetas(Progress pg) throws IOException {
                return getMetasList("*", pg);
        }
 
index 556052149d7c120305df7ab206e10b80618af703..235276c8b111d890ff878d5991e2cc9e79c54de8 100644 (file)
@@ -85,7 +85,7 @@ class CliReader extends BasicReader {
 
        @Override
        public void browse(String source) throws IOException {
-               List<MetaData> stories = getLibrary().getListBySource(source);
+               List<MetaData> stories = getLibrary().getList().filter(source, null, null);
 
                for (MetaData story : stories) {
                        String author = "";
index b1ebcc2e6971de4c25e119c5e6fbbb7a32043844..2ee319ab678b2f5c8b60c0edb2552ec0f88b4ff4 100644 (file)
@@ -243,11 +243,11 @@ class TuiReaderMainWindow extends TWindow {
 
                try {
                        if (mode == Mode.SOURCE) {
-                               metas = reader.getLibrary().getListBySource(target);
+                               metas = reader.getLibrary().getList().filter(target, null, null);
                        } else if (mode == Mode.AUTHOR) {
-                               metas = reader.getLibrary().getListByAuthor(target);
+                               metas = reader.getLibrary().getList().filter(null, target, null);
                        } else {
-                               metas = reader.getLibrary().getList();
+                               metas = reader.getLibrary().getList().getMetas();
                        }
                } catch (IOException e) {
                        Instance.getInstance().getTraceHandler().error(e);
index c163834f493f875755ac0e3d15af12263433d7a2..3cef8cfddcd48232875e64be1ee5315abfac9616 100644 (file)
@@ -17,6 +17,12 @@ import be.nikiroo.utils.StringUtils;
  * @author niki
  */
 public class GuiReaderBookInfo {
+       /**
+        * The type of {@link GuiReaderBook} (i.e., related to a story or to something else that
+        * can encompass stories).
+        * 
+        * @author niki
+        */
        public enum Type {
                /** A normal story, which can be "read". */
                STORY,
@@ -207,7 +213,7 @@ public class GuiReaderBookInfo {
 
                int size = 0;
                try {
-                       size = lib.getListBySource(source).size();
+                       size = lib.getList().filter(source, null, null).size();
                } catch (IOException e) {
                }
 
@@ -237,7 +243,7 @@ public class GuiReaderBookInfo {
 
                int size = 0;
                try {
-                       size = lib.getListByAuthor(author).size();
+                       size = lib.getList().filter(null, author, null).size();
                } catch (IOException e) {
                }
 
index 2843a0519a82c6a6771c659b6805c5baf2f4171a..a5eb6916f5972b281d7b7237a3464e2f50ee7c55 100644 (file)
@@ -363,9 +363,9 @@ class GuiReaderMainPanel extends JPanel {
                        List<MetaData> metas;
                        try {
                                if (currentType) {
-                                       metas = lib.getListBySource(value);
+                                       metas = lib.getList().filter(value, null, null);
                                } else {
-                                       metas = lib.getListByAuthor(value);
+                                       metas = lib.getList().filter(null, value, null);
                                }
                        } catch (IOException e) {
                                error(e.getLocalizedMessage(), "IOException", e);
@@ -431,13 +431,13 @@ class GuiReaderMainPanel extends JPanel {
                                break;
                        case SOURCE:
                                for (MetaData meta : helper.getReader().getLibrary()
-                                               .getListBySource(book.getInfo().getMainInfo())) {
+                                               .getList().filter(book.getInfo().getMainInfo(), null, null)) {
                                        luids.add(meta.getLuid());
                                }
                                break;
                        case AUTHOR:
                                for (MetaData meta : helper.getReader().getLibrary()
-                                               .getListByAuthor(book.getInfo().getMainInfo())) {
+                                               .getList().filter(null, book.getInfo().getMainInfo(), null)) {
                                        luids.add(meta.getLuid());
                                }
                                break;
index cf85b71e9f9b96d9e5c732122eaff202d013530d..da44438d02027f0b30f219d428bd1c466d21ea54 100644 (file)
@@ -43,7 +43,7 @@ class LibraryTest extends TestLauncher {
                                addTest(new TestCase("getList") {
                                        @Override
                                        public void test() throws Exception {
-                                               List<MetaData> metas = lib.getList();
+                                               List<MetaData> metas = lib.getList().getMetas();
                                                assertEquals(errMess, Arrays.asList(),
                                                                titlesAsList(metas));
                                        }
@@ -55,7 +55,7 @@ class LibraryTest extends TestLauncher {
                                                lib.save(story(luid1, name1, source1, author1), luid1,
                                                                null);
 
-                                               List<MetaData> metas = lib.getList();
+                                               List<MetaData> metas = lib.getList().getMetas();
                                                assertEquals(errMess, Arrays.asList(name1),
                                                                titlesAsList(metas));
                                        }
@@ -69,14 +69,14 @@ class LibraryTest extends TestLauncher {
                                                lib.save(story(luid2, name2, source2, author1), luid2,
                                                                null);
 
-                                               metas = lib.getList();
+                                               metas = lib.getList().getMetas();
                                                assertEquals(errMess, Arrays.asList(name1, name2),
                                                                titlesAsList(metas));
 
                                                lib.save(story(luid3, name3, source2, author1), luid3,
                                                                null);
 
-                                               metas = lib.getList();
+                                               metas = lib.getList().getMetas();
                                                assertEquals(errMess,
                                                                Arrays.asList(name1, name2, name3),
                                                                titlesAsList(metas));
@@ -90,7 +90,7 @@ class LibraryTest extends TestLauncher {
                                                lib.save(story(luid3, name3ex, source2, author2),
                                                                luid3, null);
 
-                                               List<MetaData> metas = lib.getList();
+                                               List<MetaData> metas = lib.getList().getMetas();
                                                assertEquals(errMess,
                                                                Arrays.asList(name1, name2, name3ex),
                                                                titlesAsList(metas));
@@ -100,7 +100,7 @@ class LibraryTest extends TestLauncher {
                                addTest(new TestCase("getList with results") {
                                        @Override
                                        public void test() throws Exception {
-                                               List<MetaData> metas = lib.getList();
+                                               List<MetaData> metas = lib.getList().getMetas();
                                                assertEquals(3, metas.size());
                                        }
                                });
@@ -110,13 +110,13 @@ class LibraryTest extends TestLauncher {
                                        public void test() throws Exception {
                                                List<MetaData> metas = null;
 
-                                               metas = lib.getListBySource(source1);
+                                               metas = lib.getList().filter(source1, null, null);
                                                assertEquals(1, metas.size());
 
-                                               metas = lib.getListBySource(source2);
+                                               metas = lib.getList().filter(source2, null, null);
                                                assertEquals(2, metas.size());
 
-                                               metas = lib.getListBySource(null);
+                                               metas = lib.getList().filter((String)null, null, null);
                                                assertEquals(3, metas.size());
                                        }
                                });
@@ -126,13 +126,13 @@ class LibraryTest extends TestLauncher {
                                        public void test() throws Exception {
                                                List<MetaData> metas = null;
 
-                                               metas = lib.getListByAuthor(author1);
+                                               metas = lib.getList().filter(null, author1, null);
                                                assertEquals(2, metas.size());
 
-                                               metas = lib.getListByAuthor(author2);
+                                               metas = lib.getList().filter(null, author2, null);
                                                assertEquals(1, metas.size());
 
-                                               metas = lib.getListByAuthor(null);
+                                               metas = lib.getList().filter((String)null, null, null);
                                                assertEquals(3, metas.size());
                                        }
                                });
@@ -144,13 +144,13 @@ class LibraryTest extends TestLauncher {
 
                                                lib.changeSource(luid3, source1, null);
 
-                                               metas = lib.getListBySource(source1);
+                                               metas = lib.getList().filter(source1, null, null);
                                                assertEquals(2, metas.size());
 
-                                               metas = lib.getListBySource(source2);
+                                               metas = lib.getList().filter(source2, null, null);
                                                assertEquals(1, metas.size());
 
-                                               metas = lib.getListBySource(null);
+                                               metas = lib.getList().filter((String)null, null, null);
                                                assertEquals(3, metas.size());
                                        }
                                });
@@ -164,13 +164,13 @@ class LibraryTest extends TestLauncher {
                                                lib.save(story(luid3, "My story 3", source2, author2),
                                                                luid3, null);
 
-                                               metas = lib.getListBySource(source1);
+                                               metas = lib.getList().filter(source1, null, null);
                                                assertEquals(1, metas.size());
 
-                                               metas = lib.getListBySource(source2);
+                                               metas = lib.getList().filter(source2, null, null);
                                                assertEquals(2, metas.size());
 
-                                               metas = lib.getListBySource(null);
+                                               metas = lib.getList().filter((String)null, null, null);
                                                assertEquals(3, metas.size());
                                        }
                                });