From 221f613b5d235a11c602b989598afe97b5b7b203 Mon Sep 17 00:00:00 2001 From: tcofoegbu Date: Thu, 20 Apr 2017 13:24:32 +0100 Subject: [PATCH] JAL-1648 refactored and improved caching architecture implementation. The improved design is centred on a custom component(JVCacheableInputBox) which wrapped around JcomoboBox --- resources/lang/Messages.properties | 2 + src/jalview/fts/api/GFTSPanelI.java | 7 ++ src/jalview/fts/core/GFTSPanel.java | 92 +-------------- src/jalview/fts/service/pdb/PDBFTSPanel.java | 5 +- .../fts/service/uniprot/UniprotFTSPanel.java | 3 +- src/jalview/gui/Finder.java | 5 +- src/jalview/io/cache/AppCache.java | 118 ++++++++++---------- src/jalview/io/cache/AppCacheI.java | 15 --- src/jalview/io/cache/CacheBoxI.java | 18 --- src/jalview/io/cache/Cacheable.java | 31 ----- src/jalview/io/cache/JvCacheableInputBox.java | 106 ++++++++++++++++++ src/jalview/jbgui/GFinder.java | 79 ++----------- 12 files changed, 196 insertions(+), 285 deletions(-) delete mode 100644 src/jalview/io/cache/AppCacheI.java delete mode 100644 src/jalview/io/cache/CacheBoxI.java delete mode 100644 src/jalview/io/cache/Cacheable.java create mode 100644 src/jalview/io/cache/JvCacheableInputBox.java diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index f284ff9..d4ae42f 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1294,3 +1294,5 @@ warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot label.invalid_name = Invalid Name ! label.output_seq_details = Output Sequence Details to list all database references label.urllinks = Links +label.default_cache_size = Default Cache Size +action.clear_cached_items = Clear Cached Items \ No newline at end of file diff --git a/src/jalview/fts/api/GFTSPanelI.java b/src/jalview/fts/api/GFTSPanelI.java index d15f2e8..99c0c51 100644 --- a/src/jalview/fts/api/GFTSPanelI.java +++ b/src/jalview/fts/api/GFTSPanelI.java @@ -138,4 +138,11 @@ public interface GFTSPanelI */ public Map getTempUserPrefs(); + /** + * Returns unique key used for storing an FTSs instance cache items in the + * cache data structure + * + * @return + */ + public String getCacheKey(); } diff --git a/src/jalview/fts/core/GFTSPanel.java b/src/jalview/fts/core/GFTSPanel.java index a338400..99192a6 100644 --- a/src/jalview/fts/core/GFTSPanel.java +++ b/src/jalview/fts/core/GFTSPanel.java @@ -29,8 +29,7 @@ import jalview.gui.IProgressIndicator; import jalview.gui.JvSwingUtils; import jalview.gui.SequenceFetcher; import jalview.io.cache.AppCache; -import jalview.io.cache.CacheBoxI; -import jalview.io.cache.Cacheable; +import jalview.io.cache.JvCacheableInputBox; import jalview.util.MessageManager; import java.awt.BorderLayout; @@ -85,7 +84,7 @@ import javax.swing.text.JTextComponent; */ @SuppressWarnings("serial") -public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable +public abstract class GFTSPanel extends JPanel implements GFTSPanelI { protected JInternalFrame mainFrame = new JInternalFrame( getFTSFrameTitle()); @@ -100,7 +99,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable protected JButton btn_cancel = new JButton(); - protected JComboBox txt_search; + protected JvCacheableInputBox txt_search; protected SequenceFetcher seqFetcher; @@ -263,10 +262,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable private void jbInit() throws Exception { - txt_search = new JComboBox(); - txt_search.setEditable(true); - txt_search - .setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + txt_search = new JvCacheableInputBox(getCacheKey()); populateCmbSearchTargetOptions(); Integer width = getTempUserPrefs().get("FTSPanel.width") == null ? 800 : getTempUserPrefs().get("FTSPanel.width"); @@ -517,7 +513,6 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable } } }); - final DeferredTextInputListener listener = new DeferredTextInputListener( 1500, new ActionListener() { @@ -656,7 +651,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable getTempUserPrefs().put("FTSPanel.x", mainFrame.getX()); getTempUserPrefs().put("FTSPanel.y", mainFrame.getY()); mainFrame.dispose(); - AppCache.getInstance().persistCache(this); + AppCache.getInstance().persistCache(getCacheKey()); } public class DeferredTextInputListener implements DocumentListener @@ -835,10 +830,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable @Override public String getTypedText() { - String typed = txt_search.getEditor().getItem() == null ? "" - : txt_search - .getEditor().getItem().toString().trim(); - return typed; + return txt_search.getUserInput(); } @Override @@ -997,77 +989,5 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI, Cacheable mainFrame.setTitle(getFTSFrameTitle()); } - @Override - public void initCache() - { - AppCache.getInstance().initCache(this); - } - - @Override - public void updateCache() - { - AppCache.getInstance().updateCache(this); - } - - - - @Override - public String getCacheKey() - { - return getCacheKey(); - } - - @Override - public CacheBoxI getCacheComboBox() - { - return new CacheBoxI() - { - - @Override - public void setSelectedItem(Object anObject) - { - txt_search.setSelectedItem(anObject); - } - - @Override - public void requestFocus() - { - txt_search.requestFocusInWindow(); - } - - @Override - public void looseFocus() - { - mainFrame.requestFocusInWindow(); - } - - @Override - public void addItem(String item) - { - txt_search.addItem(item); - } - - @Override - public void removeAllItems() - { - txt_search.removeAllItems(); - } - - @Override - public int getItemCount() - { - return txt_search.getItemCount(); - } - - @Override - public String getUserInput() - { - return txt_search.getEditor().getItem() == null ? "" : txt_search - .getEditor().getItem().toString().trim(); - } - }; - } - - } diff --git a/src/jalview/fts/service/pdb/PDBFTSPanel.java b/src/jalview/fts/service/pdb/PDBFTSPanel.java index c1e11b3..4a5f10d 100644 --- a/src/jalview/fts/service/pdb/PDBFTSPanel.java +++ b/src/jalview/fts/service/pdb/PDBFTSPanel.java @@ -51,7 +51,6 @@ public class PDBFTSPanel extends GFTSPanel this.seqFetcher = seqFetcher; this.progressIndicator = (seqFetcher == null) ? null : seqFetcher .getProgressIndicator(); - initCache(); } @Override @@ -143,8 +142,8 @@ public class PDBFTSPanel extends GFTSPanel setSearchInProgress(false); refreshPaginatorState(); updateSummaryTableSelections(); - updateCache(); } + txt_search.updateCache(); } }.start(); } @@ -278,7 +277,7 @@ public class PDBFTSPanel extends GFTSPanel return tempUserPrefs; } - @Override + public String getCacheKey() { return PDB_FTS_CACHE_KEY; diff --git a/src/jalview/fts/service/uniprot/UniprotFTSPanel.java b/src/jalview/fts/service/uniprot/UniprotFTSPanel.java index 08464c7..bff0d80 100644 --- a/src/jalview/fts/service/uniprot/UniprotFTSPanel.java +++ b/src/jalview/fts/service/uniprot/UniprotFTSPanel.java @@ -53,7 +53,6 @@ public class UniprotFTSPanel extends GFTSPanel this.seqFetcher = seqFetcher; this.progressIndicator = (seqFetcher == null) ? null : seqFetcher .getProgressIndicator(); - initCache(); } @Override @@ -142,8 +141,8 @@ public class UniprotFTSPanel extends GFTSPanel setSearchInProgress(false); refreshPaginatorState(); updateSummaryTableSelections(); - updateCache(); } + txt_search.updateCache(); } }.start(); diff --git a/src/jalview/gui/Finder.java b/src/jalview/gui/Finder.java index 8eabadb..5ca62b3 100755 --- a/src/jalview/gui/Finder.java +++ b/src/jalview/gui/Finder.java @@ -78,7 +78,6 @@ public class Finder extends GFinder { this(null, null); focusfixed = false; - initCache(); } /** @@ -332,7 +331,7 @@ public class Finder extends GFinder seqIndex = 0; } } - updateCache(); + searchBox.updateCache(); } /** @@ -388,6 +387,6 @@ public class Finder extends GFinder protected void closeAction() { frame.dispose(); - AppCache.getInstance().persistCache(this); + AppCache.getInstance().persistCache(getCacheKey()); } } diff --git a/src/jalview/io/cache/AppCache.java b/src/jalview/io/cache/AppCache.java index 46f6df2..9f9a25b 100644 --- a/src/jalview/io/cache/AppCache.java +++ b/src/jalview/io/cache/AppCache.java @@ -7,9 +7,14 @@ import java.util.Arrays; import java.util.Hashtable; import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; -public class AppCache implements AppCacheI +/** + * A singleton class used for querying and persisting cache items. + * + * @author tcnofoegbu + * + */ +public class AppCache { private static AppCache instance = null; @@ -22,10 +27,14 @@ public class AppCache implements AppCacheI cacheItems = new Hashtable>(); } - @Override - public LinkedHashSet getAllCachedItemsFor(Cacheable cacheable) + /** + * Method to obtain all the cache items for a given cache key + * + * @param cacheKey + * @return + */ + public LinkedHashSet getAllCachedItemsFor(String cacheKey) { - String cacheKey = cacheable.getCacheKey(); LinkedHashSet foundCache = cacheItems.get(cacheKey); if (foundCache == null) { @@ -36,6 +45,11 @@ public class AppCache implements AppCacheI } + /** + * Returns an singleton instance of AppCache + * + * @return + */ public static AppCache getInstance() { if (instance == null) @@ -45,60 +59,20 @@ public class AppCache implements AppCacheI return instance; } - @Override - public void updateCache(Cacheable cacheable) + /** + * Method for initialising cache items for a given cache key + * + * @param cacheKey + */ + public void initCache(String cacheKey) { - CacheBoxI cacheComboBox = cacheable.getCacheComboBox(); - String cacheKey = cacheable.getCacheKey(); - cacheComboBox.looseFocus(); - String userInput = cacheComboBox.getUserInput(); - - if (userInput != null && !userInput.isEmpty()) - { - LinkedHashSet foundCache = getAllCachedItemsFor(cacheable); - foundCache.add(userInput); - cacheItems.put(cacheKey, foundCache); - } - - String lastSearch = userInput; - if (cacheComboBox.getItemCount() > 0) - { - cacheComboBox.removeAllItems(); - } - - Set cacheItems = getAllCachedItemsFor(cacheable); - if (cacheItems != null && !cacheItems.isEmpty()) - { - for (String cacheItem : cacheItems) - { - cacheComboBox.addItem(cacheItem); - } - } - - if (!lastSearch.isEmpty()) - { - cacheComboBox.setSelectedItem(lastSearch); - cacheComboBox.requestFocus(); - } - else - { - cacheable.initCache(); - cacheComboBox.addItem(""); - cacheComboBox.setSelectedItem(""); - } - } - - @Override - public void initCache(Cacheable cacheable) - { - String separatedStr = Cache.getProperty(cacheable.getCacheKey()); + String separatedStr = Cache.getProperty(cacheKey); if (separatedStr == null || separatedStr.isEmpty()) { return; } List persistedCacheItems = Arrays.asList(separatedStr.split(CACHE_DELIMITER)); - String cacheKey = cacheable.getCacheKey(); LinkedHashSet foundCacheItems = cacheItems.get(cacheKey); if (foundCacheItems == null) @@ -111,14 +85,16 @@ public class AppCache implements AppCacheI foundCacheItems.add(cacheItem); } cacheItems.put(cacheKey, foundCacheItems); - updateCache(cacheable); } - @Override - public void persistCache(Cacheable cacheable) + /** + * Method for persisting cache items for a given cache key + * + * @param cacheKey + */ + public void persistCache(String cacheKey) { - String cacheKey = cacheable.getCacheKey(); - LinkedHashSet foundCacheItems = getAllCachedItemsFor(cacheable); + LinkedHashSet foundCacheItems = getAllCachedItemsFor(cacheKey); StringBuffer delimitedCacheBuf = new StringBuffer(); for (String cacheItem : foundCacheItems) { @@ -132,4 +108,32 @@ public class AppCache implements AppCacheI Cache.setProperty(cacheKey, delimitedCacheString); } + + public void deleteCacheItems(String cacheKey) + { + cacheItems.put(cacheKey, new LinkedHashSet()); + persistCache(cacheKey); + } + + /** + * Method for inserting cache items for given cache key into the cache data + * structure + * + * @param cacheKey + * @param cacheItems + */ + public void putCache(String cacheKey, LinkedHashSet cacheItems) + { + getCacheItems().put(cacheKey, cacheItems); + } + + /** + * Getter method for obtaining cache data structure + * + * @return + */ + private Hashtable> getCacheItems() + { + return cacheItems; + } } diff --git a/src/jalview/io/cache/AppCacheI.java b/src/jalview/io/cache/AppCacheI.java deleted file mode 100644 index 8d9e9f9..0000000 --- a/src/jalview/io/cache/AppCacheI.java +++ /dev/null @@ -1,15 +0,0 @@ -package jalview.io.cache; - -import java.util.Set; - -public interface AppCacheI -{ - - public void initCache(Cacheable cacheable); - - public void updateCache(Cacheable cacheable); - - public void persistCache(Cacheable cacheable); - - public Set getAllCachedItemsFor(Cacheable cacheable); -} diff --git a/src/jalview/io/cache/CacheBoxI.java b/src/jalview/io/cache/CacheBoxI.java deleted file mode 100644 index c9b65fe..0000000 --- a/src/jalview/io/cache/CacheBoxI.java +++ /dev/null @@ -1,18 +0,0 @@ -package jalview.io.cache; - -public interface CacheBoxI -{ - public void setSelectedItem(Object anObject); - - public void requestFocus(); - - public void looseFocus(); - - public void addItem(E item); - - public void removeAllItems(); - - public int getItemCount(); - - public String getUserInput(); -} diff --git a/src/jalview/io/cache/Cacheable.java b/src/jalview/io/cache/Cacheable.java deleted file mode 100644 index 0287457..0000000 --- a/src/jalview/io/cache/Cacheable.java +++ /dev/null @@ -1,31 +0,0 @@ -package jalview.io.cache; - - -public interface Cacheable -{ - - /** - * method executed on cache initialisation - */ - public void initCache(); - - /** - * method executed on cache update - */ - public void updateCache(); - - /** - * Combo-box instance for the cache component - * - * @return - */ - public CacheBoxI getCacheComboBox(); - - /** - * The unique key that will be used for storing user input for this cacheable - * in the cache dictionary - * - * @return - */ - public String getCacheKey(); -} diff --git a/src/jalview/io/cache/JvCacheableInputBox.java b/src/jalview/io/cache/JvCacheableInputBox.java new file mode 100644 index 0000000..55254c5 --- /dev/null +++ b/src/jalview/io/cache/JvCacheableInputBox.java @@ -0,0 +1,106 @@ +package jalview.io.cache; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.JComboBox; +import javax.swing.SwingUtilities; + +public class JvCacheableInputBox extends JComboBox +{ + + private static final long serialVersionUID = 5774610435079326695L; + + private String cacheKey; + + private AppCache appCache; + + public JvCacheableInputBox(String cacheKey) + { + super(); + this.cacheKey = cacheKey; + setEditable(true); + setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + appCache = AppCache.getInstance(); + appCache.initCache(cacheKey); + updateCache(); + } + + + /** + * Answers true if input text is an integer + * + * @param text + * @return + */ + private boolean isInteger(String text) + { + try + { + Integer.parseInt(text); + return true; + } catch (NumberFormatException e) + { + return false; + } + } + + /** + * Method called to update the cache with the last user input + */ + public void updateCache() + { + SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + String userInput = getUserInput(); + if (userInput != null && !userInput.isEmpty()) + { + LinkedHashSet foundCache = appCache + .getAllCachedItemsFor(cacheKey); + // remove old cache item so as to place current input at the top of + // the result + foundCache.remove(userInput); + foundCache.add(userInput); + appCache.putCache(cacheKey, foundCache); + } + + String lastSearch = userInput; + if (getItemCount() > 0) + { + removeAllItems(); + } + Set cacheItems = appCache.getAllCachedItemsFor(cacheKey); + List reversedCacheItems = new ArrayList(); + reversedCacheItems.addAll(cacheItems); + cacheItems = null; + Collections.reverse(reversedCacheItems); + if (lastSearch.isEmpty()) + { + addItem(""); + } + if (reversedCacheItems != null && !reversedCacheItems.isEmpty()) + { + for (String cacheItem : reversedCacheItems) + { + addItem(cacheItem); + } + } + setSelectedItem(lastSearch.isEmpty() ? "" : lastSearch); + } + }); + } + + + public String getUserInput() + { + return getEditor().getItem() == null ? "" : getEditor().getItem() + .toString().trim(); + } + +} diff --git a/src/jalview/jbgui/GFinder.java b/src/jalview/jbgui/GFinder.java index f676a49..144c67d 100755 --- a/src/jalview/jbgui/GFinder.java +++ b/src/jalview/jbgui/GFinder.java @@ -24,9 +24,7 @@ import jalview.datamodel.AlignmentI; import jalview.io.DataSourceType; import jalview.io.FileFormat; import jalview.io.FormatAdapter; -import jalview.io.cache.AppCache; -import jalview.io.cache.CacheBoxI; -import jalview.io.cache.Cacheable; +import jalview.io.cache.JvCacheableInputBox; import jalview.util.MessageManager; import java.awt.BorderLayout; @@ -39,7 +37,6 @@ import java.awt.event.KeyEvent; import javax.swing.JButton; import javax.swing.JCheckBox; -import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; @@ -48,7 +45,7 @@ import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.text.JTextComponent; -public class GFinder extends JPanel implements Cacheable +public class GFinder extends JPanel { JLabel jLabelFind = new JLabel(); @@ -62,7 +59,7 @@ public class GFinder extends JPanel implements Cacheable protected JButton createNewGroup = new JButton(); - protected JComboBox searchBox = new JComboBox(); + protected JvCacheableInputBox searchBox = new JvCacheableInputBox(getCacheKey()); BorderLayout mainBorderLayout = new BorderLayout(); @@ -137,9 +134,6 @@ public class GFinder extends JPanel implements Cacheable } }); searchBox.setFont(new java.awt.Font("Verdana", Font.PLAIN, 12)); - searchBox.setEditable(true); - searchBox -.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXX"); ((JTextComponent) searchBox.getEditor().getEditorComponent()) .addCaretListener(new CaretListener() { @@ -247,73 +241,18 @@ public class GFinder extends JPanel implements Cacheable - @Override - public CacheBoxI getCacheComboBox() - { - return new CacheBoxI() - { - - @Override - public void setSelectedItem(Object anObject) - { - searchBox.setSelectedItem(anObject); - } - - @Override - public void requestFocus() - { - searchBox.requestFocusInWindow(); - } - - @Override - public void looseFocus() - { - jPanel6.requestFocusInWindow(); - } - - @Override - public void addItem(String item) - { - searchBox.addItem(item); - } - @Override - public void removeAllItems() - { - searchBox.removeAllItems(); - } - - @Override - public int getItemCount() - { - return searchBox.getItemCount(); - } - - @Override - public String getUserInput() - { - return searchBox.getEditor().getItem() == null ? "" : searchBox - .getEditor().getItem().toString().trim(); - } - }; - } - - @Override + /** + * Returns unique key used for storing Finder cache items in the cache data + * structure + * + * @return + */ public String getCacheKey() { return FINDER_CACHE_KEY; } - @Override - public void initCache() - { - AppCache.getInstance().initCache(this); - } - @Override - public void updateCache() - { - AppCache.getInstance().updateCache(this); - } } -- 1.7.10.2