JAL-4036 New configuration, target and pagination process for 2022-07 new Uniprot API
[jalview.git] / src / jalview / fts / service / uniprot / UniprotFTSPanel.java
index 32f359e..0d9767c 100644 (file)
 
 package jalview.fts.service.uniprot;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import javax.help.HelpSetException;
+
+import jalview.bin.Console;
 import jalview.fts.api.FTSDataColumnI;
 import jalview.fts.api.FTSRestClientI;
 import jalview.fts.core.FTSRestRequest;
 import jalview.fts.core.FTSRestResponse;
 import jalview.fts.core.GFTSPanel;
+import jalview.gui.Help;
+import jalview.gui.Help.HelpId;
 import jalview.gui.SequenceFetcher;
 import jalview.util.MessageManager;
 
-import java.util.HashSet;
-
 @SuppressWarnings("serial")
 public class UniprotFTSPanel extends GFTSPanel
 {
@@ -38,91 +45,113 @@ public class UniprotFTSPanel extends GFTSPanel
   private static String defaultFTSFrameTitle = MessageManager
           .getString("label.uniprot_sequence_fetcher");
 
-  private String ftsFrameTitle = defaultFTSFrameTitle;
-
-  private int resultSetCount;
+  private static Map<String, Integer> tempUserPrefs = new HashMap<>();
 
-  private int offSet;
+  private static final String UNIPROT_FTS_CACHE_KEY = "CACHE.UNIPROT_FTS";
 
-  private static int pageLimit = UniProtFTSRestClient.getInstance()
-          .getDefaultResponsePageSize();
+  private static final String UNIPROT_AUTOSEARCH = "FTS.UNIPROT.AUTOSEARCH";
 
-  public UniprotFTSPanel(SequenceFetcher seqFetcher)
+  /**
+   * Constructor given an (optional) sequence fetcher panel to revert to on
+   * clicking the 'Back' button
+   * 
+   * @param fetcher
+   */
+  public UniprotFTSPanel(SequenceFetcher fetcher)
   {
-    this.seqFetcher = seqFetcher;
-    this.progressIdicator = (seqFetcher == null) ? null : seqFetcher
-            .getProgressIndicator();
+    super(fetcher);
+    pageLimit = UniProtFTSRestClient.getInstance()
+            .getDefaultResponsePageSize();
+    this.seqFetcher = fetcher;
+    this.progressIndicator = (fetcher == null) ? null
+            : fetcher.getProgressIndicator();
   }
 
   @Override
-  public void searchAction()
+  public void searchAction(boolean isFreshSearch)
   {
-    offSet = 0;
-    executeSearch();
+    searchAction(null, isFreshSearch);
   }
 
-  public void executeSearch()
+  public void searchAction(String cursor, boolean isFreshSearch)
   {
+    mainFrame.requestFocusInWindow();
+    if (isFreshSearch)
+    {
+      offSet = 0;
+      UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
+      c.clearCursors();
+      c.setCursorPage(0);
+      c.setCursor(0, "");
+    }
     new Thread()
-  {
+    {
       @Override
       public void run()
       {
-        ftsFrameTitle = defaultFTSFrameTitle;
         reset();
-        if (getTypedText().length() > 0)
+        String searchInput = getTypedText();
+        if (searchInput.length() > 0)
         {
           setSearchInProgress(true);
           long startTime = System.currentTimeMillis();
-
+          searchInput = getTypedText();
           String searchTarget = ((FTSDataColumnI) cmb_searchTarget
                   .getSelectedItem()).getAltCode();
-
           wantedFields = UniProtFTSRestClient.getInstance()
-                  .getAllDefaulDisplayedDataColumns();
-          String searchTerm = txt_search.getText();
+                  .getAllDefaultDisplayedFTSDataColumns();
+          String searchTerm = decodeSearchTerm(searchInput, searchTarget);
 
           FTSRestRequest request = new FTSRestRequest();
           request.setFieldToSearchBy(searchTarget);
           request.setSearchTerm(searchTerm);
           request.setOffSet(offSet);
           request.setWantedFields(wantedFields);
-          FTSRestClientI uniProtRestCleint = UniProtFTSRestClient
+          UniProtFTSRestClient uniProtRestClient = UniProtFTSRestClient
                   .getInstance();
           FTSRestResponse resultList;
           try
           {
-            resultList = uniProtRestCleint.executeRequest(request);
+            resultList = uniProtRestClient.executeRequest(request, cursor);
           } catch (Exception e)
           {
-            e.printStackTrace();
             setErrorMessage(e.getMessage());
             checkForErrors();
+            setSearchInProgress(false);
             return;
           }
 
           if (resultList.getSearchSummary() != null
                   && resultList.getSearchSummary().size() > 0)
           {
-            getResultTable().setModel(
-                    FTSRestResponse.getTableModel(request,
-                            resultList.getSearchSummary()));
+            getResultTable().setModel(FTSRestResponse.getTableModel(request,
+                    resultList.getSearchSummary()));
             FTSRestResponse.configureTableColumn(getResultTable(),
-                    wantedFields);
+                    wantedFields, tempUserPrefs);
             getResultTable().setVisible(true);
           }
 
           long endTime = System.currentTimeMillis();
-          resultSetCount = resultList.getNumberOfItemsFound();
-          String result = (resultSetCount > 0) ? MessageManager
-                  .getString("label.results") : MessageManager
-                  .getString("label.result");
+          totalResultSetCount = resultList.getNumberOfItemsFound();
+          resultSetCount = resultList.getSearchSummary() == null ? 0
+                  : resultList.getSearchSummary().size();
+          String result = (resultSetCount > 0)
+                  ? MessageManager.getString("label.results")
+                  : MessageManager.getString("label.result");
           if (isPaginationEnabled() && resultSetCount > 0)
           {
-            updateSearchFrameTitle(defaultFTSFrameTitle + " - " + result
-                    + " " + (offSet + 1) + " to "
-                    + (offSet + resultSetCount)
-                    + " " + " (" + (endTime - startTime) + " milli secs)");
+            updateSearchFrameTitle(
+                    defaultFTSFrameTitle + " - " + result + " "
+                            + totalNumberformatter
+                                    .format(Integer.valueOf(offSet + 1))
+                            + " to "
+                            + totalNumberformatter.format(Integer
+                                    .valueOf(offSet + resultSetCount))
+                            + " of "
+                            + totalNumberformatter.format(
+                                    Integer.valueOf(totalResultSetCount))
+                            + " " + " (" + (endTime - startTime)
+                            + " milli secs)");
           }
           else
           {
@@ -132,49 +161,39 @@ public class UniprotFTSPanel extends GFTSPanel
           }
           setSearchInProgress(false);
           refreshPaginatorState();
+          updateSummaryTableSelections();
         }
+        txt_search.updateCache();
       }
     }.start();
 
   }
 
-
-
-  public void refreshPaginatorState()
+  public String decodeSearchTerm(String enteredText, String targetField)
   {
-    // System.out.println("resultSet count : " + resultSetCount);
-    // System.out.println("offSet : " + offSet);
-    // System.out.println("page limit : " + pageLimit);
-    setPrevPageButtonEnabled(false);
-    setNextPageButtonEnabled(false);
-    if (resultSetCount >= pageLimit)
-    {
-      setNextPageButtonEnabled(true);
-    }
-    if (offSet >= pageLimit)
+    int searchTargetLength = targetField.equalsIgnoreCase("Search All") ? 0
+            : targetField.length() + 1;
+    String searchTarget = targetField.equalsIgnoreCase("Search All") ? ""
+            : targetField + ":";
+    String foundSearchTerms = enteredText;
+    StringBuilder foundSearchTermsBuilder = new StringBuilder();
+    if (enteredText.contains(";"))
     {
-      setPrevPageButtonEnabled(true);
-    }
-  }
-
-  @Override
-  public void prevPageAction()
-  {
-    if (offSet >= pageLimit)
-    {
-      offSet = offSet - pageLimit;
-      executeSearch();
-    }else{
-      refreshPaginatorState();
+      String[] searchTerms = enteredText.split(";");
+      for (String searchTerm : searchTerms)
+      {
+        foundSearchTermsBuilder.append(searchTarget).append(searchTerm)
+                .append(" OR ");
+      }
+      int endIndex = foundSearchTermsBuilder.lastIndexOf(" OR ");
+      foundSearchTerms = foundSearchTermsBuilder.toString();
+      if (foundSearchTerms.contains(" OR "))
+      {
+        foundSearchTerms = foundSearchTerms.substring(searchTargetLength,
+                endIndex);
+      }
     }
-  }
-
-  @Override
-  public void nextPageAction()
-  {
-    offSet = offSet + pageLimit;
-    executeSearch();
-
+    return foundSearchTerms;
   }
 
   @Override
@@ -188,12 +207,12 @@ public class UniprotFTSPanel extends GFTSPanel
   {
     disableActionButtons();
     StringBuilder selectedIds = new StringBuilder();
-    HashSet<String> selectedIdsSet = new HashSet<String>();
+    HashSet<String> selectedIdsSet = new HashSet<>();
     int primaryKeyColIndex = 0;
     try
     {
-      primaryKeyColIndex = getFTSRestClient().getPrimaryKeyColumIndex(
-              wantedFields, false);
+      primaryKeyColIndex = getFTSRestClient()
+              .getPrimaryKeyColumIndex(wantedFields, false);
     } catch (Exception e)
     {
       e.printStackTrace();
@@ -201,19 +220,18 @@ public class UniprotFTSPanel extends GFTSPanel
     int[] selectedRows = getResultTable().getSelectedRows();
     for (int summaryRow : selectedRows)
     {
-      String idStr = getResultTable().getValueAt(summaryRow,
-              primaryKeyColIndex).toString();
+      String idStr = getResultTable()
+              .getValueAt(summaryRow, primaryKeyColIndex).toString();
       selectedIdsSet.add(idStr);
     }
-
+    selectedIdsSet.addAll(paginatorCart);
     for (String selectedId : selectedIdsSet)
     {
       selectedIds.append(selectedId).append(";");
     }
 
     String ids = selectedIds.toString();
-    // System.out.println(">>>>>>>>>>>>>>>> selected Ids: " + ids);
-    seqFetcher.getTextArea().setText(ids);
+    seqFetcher.setQuery(ids);
     Thread worker = new Thread(seqFetcher);
     worker.start();
     delayAndEnableActionButtons();
@@ -228,7 +246,100 @@ public class UniprotFTSPanel extends GFTSPanel
   @Override
   public String getFTSFrameTitle()
   {
-    return ftsFrameTitle;
+    return defaultFTSFrameTitle;
+  }
+
+  @Override
+  public Map<String, Integer> getTempUserPrefs()
+  {
+    return tempUserPrefs;
+  }
+
+  @Override
+  public String getCacheKey()
+  {
+    return UNIPROT_FTS_CACHE_KEY;
+  }
+
+  @Override
+  public String getAutosearchPreference()
+  {
+    return UNIPROT_AUTOSEARCH;
+  }
+
+  @Override
+  protected void showHelp()
+  {
+    try
+    {
+      Help.showHelpWindow(HelpId.UniprotFts);
+    } catch (HelpSetException e1)
+    {
+      e1.printStackTrace();
+    }
+  }
+
+  /*
+   * 2022-07-20 bsoares
+   * The new Uniprot API has a strange pagination process described at
+   * https://www.uniprot.org/help/pagination
+   * When a successful request returns results, with more results past the size
+   * limit, the response sends a "Link" header with a URL containing the a "cursor"
+   * parameter with an opaque string that refers to the next page of results.
+   * These are store as nextCursor in the UniProtFTSRestClient along with the currCursor.
+   * When navigation across pages occurs these should be swapped around.
+   */
+  @Override
+  public void refreshPaginatorState()
+  {
+    UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
+    setNextPageButtonEnabled(c.getNextCursor() != null);
+    setPrevPageButtonEnabled(c.getPrevCursor() != null);
+  }
+
+  @Override
+  public void prevPageAction()
+  {
+    updatePaginatorCart();
+    UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
+    String prevCursor = c.getPrevCursor();
+    if (prevCursor != null)
+    {
+      if (offSet >= pageLimit)
+      {
+        offSet -= pageLimit;
+      }
+      else
+      {
+        // not sure what's happening if we get here though it wouldn't surprise
+        // me
+        Console.warn(
+                "UniprotFTSPanel: prevCursor exists but offset < pageLimit. This probably shouldn't be happening.");
+      }
+      c.setPrevCursorPage();
+      searchAction(prevCursor, false);
+    }
+    else
+    {
+      refreshPaginatorState();
+    }
+  }
+
+  @Override
+  public void nextPageAction()
+  {
+    UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
+    String nextCursor = c.getNextCursor();
+    if (nextCursor != null)
+    {
+      offSet += pageLimit;
+      c.setNextCursorPage();
+      searchAction(nextCursor, false);
+    }
+    else
+    {
+      refreshPaginatorState();
+    }
   }
 
 }