JAL-2484 added improvement to enable clearing cache items and configuring maximum...
authortcofoegbu <tcnofoegbu@dundee.ac.uk>
Thu, 20 Apr 2017 16:41:50 +0000 (17:41 +0100)
committertcofoegbu <tcnofoegbu@dundee.ac.uk>
Thu, 20 Apr 2017 16:41:50 +0000 (17:41 +0100)
src/jalview/fts/core/GFTSPanel.java
src/jalview/gui/Finder.java
src/jalview/io/cache/AppCache.java
src/jalview/io/cache/JvCacheableInputBox.java

index 99192a6..8b04959 100644 (file)
@@ -28,7 +28,6 @@ import jalview.gui.Desktop;
 import jalview.gui.IProgressIndicator;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.SequenceFetcher;
-import jalview.io.cache.AppCache;
 import jalview.io.cache.JvCacheableInputBox;
 import jalview.util.MessageManager;
 
@@ -651,7 +650,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
     getTempUserPrefs().put("FTSPanel.x", mainFrame.getX());
     getTempUserPrefs().put("FTSPanel.y", mainFrame.getY());
     mainFrame.dispose();
-    AppCache.getInstance().persistCache(getCacheKey());
+    txt_search.persistCache();
   }
 
   public class DeferredTextInputListener implements DocumentListener
index 5ca62b3..0f8bb5e 100755 (executable)
@@ -24,7 +24,6 @@ import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.io.cache.AppCache;
 import jalview.jbgui.GFinder;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
@@ -387,6 +386,6 @@ public class Finder extends GFinder
   protected void closeAction()
   {
     frame.dispose();
-    AppCache.getInstance().persistCache(getCacheKey());
+    searchBox.persistCache();
   }
 }
index 9f9a25b..8ed33e6 100644 (file)
@@ -20,6 +20,10 @@ public class AppCache
 
   private Hashtable<String, LinkedHashSet<String>> cacheItems;
 
+  private static final String DEFAULT_LIMIT_KEY = ".DEFAULT_LIMIT";
+
+  private static final String DEFAULT_LIMIT = "99";
+
   private static final String CACHE_DELIMITER = ";";
 
   private AppCache()
@@ -115,6 +119,25 @@ public class AppCache
     persistCache(cacheKey);
   }
 
+  public String getCacheLmit(String cacheKey)
+  {
+    String uniqueKey = cacheKey + DEFAULT_LIMIT_KEY;
+    return Cache.getDefault(uniqueKey, DEFAULT_LIMIT);
+  }
+
+  public int updateCacheLimit(String cacheKey, String newLimit)
+  {
+    String uniqueKey = cacheKey + DEFAULT_LIMIT_KEY;
+    String formerLimit = getCacheLmit(cacheKey);
+    if (newLimit != null && !newLimit.isEmpty()
+            && !formerLimit.equals(newLimit))
+    {
+      Cache.setProperty(uniqueKey, newLimit);
+      formerLimit = newLimit;
+    }
+    return Integer.valueOf(formerLimit);
+  }
+
   /**
    * Method for inserting cache items for given cache key into the cache data
    * structure
index 55254c5..3eb193e 100644 (file)
@@ -1,5 +1,11 @@
 package jalview.io.cache;
 
+import jalview.util.MessageManager;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -7,7 +13,15 @@ import java.util.List;
 import java.util.Set;
 
 import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.PlainDocument;
 
 public class JvCacheableInputBox<E> extends JComboBox<String>
 {
@@ -18,6 +32,20 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
 
   private AppCache appCache;
 
+  JPanel pnlDefaultCache = new JPanel();
+
+  JLabel lblDefaultCacheSize = new JLabel();
+
+  JTextField txtDefaultCacheSize = new JTextField();
+
+  JPopupMenu popup = new JPopupMenu();
+
+  JMenuItem menuItemClearCache = new JMenuItem();
+
+  final static int INPUT_LIMIT = 2;
+
+  final static String SPACE = "    ";
+
   public JvCacheableInputBox(String cacheKey)
   {
     super();
@@ -25,12 +53,61 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
     setEditable(true);
     setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
     appCache = AppCache.getInstance();
+    initCachePopupMenu();
     appCache.initCache(cacheKey);
     updateCache();
   }
 
 
   /**
+   * Initialise this cache's pop-up menu
+   */
+  private void initCachePopupMenu()
+  {
+    add(popup);
+    setComponentPopupMenu(popup);
+    pnlDefaultCache.setBackground(Color.WHITE);
+    txtDefaultCacheSize.setPreferredSize(new Dimension(45, 20));
+    lblDefaultCacheSize.setText(SPACE
+            + MessageManager.getString("label.default_cache_size"));
+    // Force input to accept only Integer entries up to length - INPUT_LIMIT
+    txtDefaultCacheSize.setDocument(new PlainDocument()
+    {
+      private static final long serialVersionUID = 1L;
+
+      @Override
+      public void insertString(int offs, String str, AttributeSet a)
+              throws BadLocationException
+      {
+        if (getLength() + str.length() <= INPUT_LIMIT && isInteger(str))
+        {
+          super.insertString(offs, str, a);
+        }
+      }
+    });
+    txtDefaultCacheSize.setText(appCache.getCacheLmit(cacheKey));
+    pnlDefaultCache.add(lblDefaultCacheSize);
+    pnlDefaultCache.add(txtDefaultCacheSize);
+    popup.insert(pnlDefaultCache, 0);
+
+    menuItemClearCache.setText(MessageManager
+            .getString("action.clear_cached_items"));
+    menuItemClearCache.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        System.out.println(">>>>> Clear cache items");
+        setSelectedItem("");
+        appCache.deleteCacheItems(cacheKey);
+        updateCache();
+      }
+    });
+
+    popup.add(menuItemClearCache);
+  }
+
+  /**
    * Answers true if input text is an integer
    * 
    * @param text
@@ -58,6 +135,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       @Override
       public void run()
       {
+        int cacheLimit = appCache.updateCacheLimit(cacheKey,
+                txtDefaultCacheSize.getText());
         String userInput = getUserInput();
         if (userInput != null && !userInput.isEmpty())
         {
@@ -84,12 +163,34 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
         {
           addItem("");
         }
+
         if (reversedCacheItems != null && !reversedCacheItems.isEmpty())
         {
+          LinkedHashSet<String> foundCache = appCache
+                  .getAllCachedItemsFor(cacheKey);
+          boolean prune = reversedCacheItems.size() > cacheLimit;
+          int count = 1;
+          boolean limitExceeded = false;
           for (String cacheItem : reversedCacheItems)
           {
-            addItem(cacheItem);
+            limitExceeded = (count++ > cacheLimit);
+            if (prune)
+            {
+              if (limitExceeded)
+              {
+                foundCache.remove(cacheItem);
+              }
+              else
+              {
+                addItem(cacheItem);
+              }
+            }
+            else
+            {
+              addItem(cacheItem);
+            }
           }
+          appCache.putCache(cacheKey, foundCache);
         }
         setSelectedItem(lastSearch.isEmpty() ? "" : lastSearch);
       }
@@ -97,6 +198,21 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   }
 
 
+  /**
+   * This method should be called to persist the in-memory cache when this
+   * components parent frame is closed / exited
+   */
+  public void persistCache()
+  {
+    appCache.persistCache(cacheKey);
+    appCache.updateCacheLimit(cacheKey, txtDefaultCacheSize.getText());
+  }
+
+  /**
+   * Method to obtain input text from the cache box
+   * 
+   * @return
+   */
   public String getUserInput()
   {
     return getEditor().getItem() == null ? "" : getEditor().getItem()