JAL-4036 Add getDbName to the GFTSPanelI and add an index code message to the index...
[jalview.git] / src / jalview / fts / service / uniprot / UniprotFTSPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21
22 package jalview.fts.service.uniprot;
23
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27
28 import javax.help.HelpSetException;
29
30 import jalview.bin.Console;
31 import jalview.fts.api.FTSDataColumnI;
32 import jalview.fts.api.FTSRestClientI;
33 import jalview.fts.core.FTSRestRequest;
34 import jalview.fts.core.FTSRestResponse;
35 import jalview.fts.core.GFTSPanel;
36 import jalview.gui.Help;
37 import jalview.gui.Help.HelpId;
38 import jalview.gui.SequenceFetcher;
39 import jalview.util.MessageManager;
40
41 @SuppressWarnings("serial")
42 public class UniprotFTSPanel extends GFTSPanel
43 {
44
45   private static String defaultFTSFrameTitle = MessageManager
46           .getString("label.uniprot_sequence_fetcher");
47
48   private static Map<String, Integer> tempUserPrefs = new HashMap<>();
49
50   private static final String UNIPROT_FTS_CACHE_KEY = "CACHE.UNIPROT_FTS";
51
52   private static final String UNIPROT_AUTOSEARCH = "FTS.UNIPROT.AUTOSEARCH";
53
54   /**
55    * Constructor given an (optional) sequence fetcher panel to revert to on
56    * clicking the 'Back' button
57    * 
58    * @param fetcher
59    */
60   public UniprotFTSPanel(SequenceFetcher fetcher)
61   {
62     super(fetcher);
63     pageLimit = UniProtFTSRestClient.getInstance()
64             .getDefaultResponsePageSize();
65     this.seqFetcher = fetcher;
66     this.progressIndicator = (fetcher == null) ? null
67             : fetcher.getProgressIndicator();
68   }
69
70   @Override
71   public void searchAction(boolean isFreshSearch)
72   {
73     searchAction(null, isFreshSearch);
74   }
75
76   public void searchAction(String cursor, boolean isFreshSearch)
77   {
78     mainFrame.requestFocusInWindow();
79     if (isFreshSearch)
80     {
81       offSet = 0;
82       UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
83       c.clearCursors();
84       c.setCursorPage(0);
85       c.setCursor(0, "");
86     }
87     new Thread()
88     {
89       @Override
90       public void run()
91       {
92         reset();
93         String searchInput = getTypedText();
94         if (searchInput.length() > 0)
95         {
96           setSearchInProgress(true);
97           long startTime = System.currentTimeMillis();
98           searchInput = getTypedText();
99           String searchTarget = ((FTSDataColumnI) cmb_searchTarget
100                   .getSelectedItem()).getAltCode();
101           wantedFields = UniProtFTSRestClient.getInstance()
102                   .getAllDefaultDisplayedFTSDataColumns();
103           String searchTerm = decodeSearchTerm(searchInput, searchTarget);
104
105           FTSRestRequest request = new FTSRestRequest();
106           request.setFieldToSearchBy(searchTarget);
107           request.setSearchTerm(searchTerm);
108           request.setOffSet(offSet);
109           request.setWantedFields(wantedFields);
110           UniProtFTSRestClient uniProtRestClient = UniProtFTSRestClient
111                   .getInstance();
112           FTSRestResponse resultList;
113           try
114           {
115             resultList = uniProtRestClient.executeRequest(request, cursor);
116           } catch (Exception e)
117           {
118             setErrorMessage(e.getMessage());
119             checkForErrors();
120             setSearchInProgress(false);
121             return;
122           }
123
124           if (resultList.getSearchSummary() != null
125                   && resultList.getSearchSummary().size() > 0)
126           {
127             getResultTable().setModel(FTSRestResponse.getTableModel(request,
128                     resultList.getSearchSummary()));
129             FTSRestResponse.configureTableColumn(getResultTable(),
130                     wantedFields, tempUserPrefs);
131             getResultTable().setVisible(true);
132           }
133
134           long endTime = System.currentTimeMillis();
135           totalResultSetCount = resultList.getNumberOfItemsFound();
136           resultSetCount = resultList.getSearchSummary() == null ? 0
137                   : resultList.getSearchSummary().size();
138           String result = (resultSetCount > 0)
139                   ? MessageManager.getString("label.results")
140                   : MessageManager.getString("label.result");
141           if (isPaginationEnabled() && resultSetCount > 0)
142           {
143             updateSearchFrameTitle(
144                     defaultFTSFrameTitle + " - " + result + " "
145                             + totalNumberformatter
146                                     .format(Integer.valueOf(offSet + 1))
147                             + " to "
148                             + totalNumberformatter.format(Integer
149                                     .valueOf(offSet + resultSetCount))
150                             + " of "
151                             + totalNumberformatter.format(
152                                     Integer.valueOf(totalResultSetCount))
153                             + " " + " (" + (endTime - startTime)
154                             + " milli secs)");
155           }
156           else
157           {
158             updateSearchFrameTitle(defaultFTSFrameTitle + " - "
159                     + resultSetCount + " " + result + " ("
160                     + (endTime - startTime) + " milli secs)");
161           }
162           setSearchInProgress(false);
163           refreshPaginatorState();
164           updateSummaryTableSelections();
165         }
166         txt_search.updateCache();
167       }
168     }.start();
169
170   }
171
172   public String decodeSearchTerm(String enteredText, String targetField)
173   {
174     int searchTargetLength = targetField.equalsIgnoreCase("Search All") ? 0
175             : targetField.length() + 1;
176     String searchTarget = targetField.equalsIgnoreCase("Search All") ? ""
177             : targetField + ":";
178     String foundSearchTerms = enteredText;
179     StringBuilder foundSearchTermsBuilder = new StringBuilder();
180     if (enteredText.contains(";"))
181     {
182       String[] searchTerms = enteredText.split(";");
183       for (String searchTerm : searchTerms)
184       {
185         foundSearchTermsBuilder.append(searchTarget).append(searchTerm)
186                 .append(" OR ");
187       }
188       int endIndex = foundSearchTermsBuilder.lastIndexOf(" OR ");
189       foundSearchTerms = foundSearchTermsBuilder.toString();
190       if (foundSearchTerms.contains(" OR "))
191       {
192         foundSearchTerms = foundSearchTerms.substring(searchTargetLength,
193                 endIndex);
194       }
195     }
196     return foundSearchTerms;
197   }
198
199   @Override
200   public boolean isPaginationEnabled()
201   {
202     return true;
203   }
204
205   @Override
206   public void okAction()
207   {
208     disableActionButtons();
209     StringBuilder selectedIds = new StringBuilder();
210     HashSet<String> selectedIdsSet = new HashSet<>();
211     int primaryKeyColIndex = 0;
212     try
213     {
214       primaryKeyColIndex = getFTSRestClient()
215               .getPrimaryKeyColumIndex(wantedFields, false);
216     } catch (Exception e)
217     {
218       e.printStackTrace();
219     }
220     int[] selectedRows = getResultTable().getSelectedRows();
221     for (int summaryRow : selectedRows)
222     {
223       String idStr = getResultTable()
224               .getValueAt(summaryRow, primaryKeyColIndex).toString();
225       selectedIdsSet.add(idStr);
226     }
227     selectedIdsSet.addAll(paginatorCart);
228     for (String selectedId : selectedIdsSet)
229     {
230       selectedIds.append(selectedId).append(";");
231     }
232
233     String ids = selectedIds.toString();
234     seqFetcher.setQuery(ids);
235     Thread worker = new Thread(seqFetcher);
236     worker.start();
237     delayAndEnableActionButtons();
238   }
239
240   @Override
241   public FTSRestClientI getFTSRestClient()
242   {
243     return UniProtFTSRestClient.getInstance();
244   }
245
246   @Override
247   public String getFTSFrameTitle()
248   {
249     return defaultFTSFrameTitle;
250   }
251
252   @Override
253   public Map<String, Integer> getTempUserPrefs()
254   {
255     return tempUserPrefs;
256   }
257
258   @Override
259   public String getCacheKey()
260   {
261     return UNIPROT_FTS_CACHE_KEY;
262   }
263
264   @Override
265   public String getAutosearchPreference()
266   {
267     return UNIPROT_AUTOSEARCH;
268   }
269
270   @Override
271   protected void showHelp()
272   {
273     try
274     {
275       Help.showHelpWindow(HelpId.UniprotFts);
276     } catch (HelpSetException e1)
277     {
278       e1.printStackTrace();
279     }
280   }
281
282   /*
283    * 2022-07-20 bsoares
284    * The new Uniprot API has a strange pagination process described at
285    * https://www.uniprot.org/help/pagination
286    * When a successful request returns results, with more results past the size
287    * limit, the response sends a "Link" header with a URL containing the a "cursor"
288    * parameter with an opaque string that refers to the next page of results.
289    * These are store as nextCursor in the UniProtFTSRestClient along with the currCursor.
290    * When navigation across pages occurs these should be swapped around.
291    */
292   @Override
293   public void refreshPaginatorState()
294   {
295     UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
296     setNextPageButtonEnabled(c.getNextCursor() != null);
297     setPrevPageButtonEnabled(c.getPrevCursor() != null);
298   }
299
300   @Override
301   public void prevPageAction()
302   {
303     updatePaginatorCart();
304     UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
305     String prevCursor = c.getPrevCursor();
306     if (prevCursor != null)
307     {
308       if (offSet >= pageLimit)
309       {
310         offSet -= pageLimit;
311       }
312       else
313       {
314         // not sure what's happening if we get here though it wouldn't surprise
315         // me
316         Console.warn(
317                 "UniprotFTSPanel: prevCursor exists but offset < pageLimit. This probably shouldn't be happening.");
318       }
319       c.setPrevCursorPage();
320       searchAction(prevCursor, false);
321     }
322     else
323     {
324       refreshPaginatorState();
325     }
326   }
327
328   @Override
329   public void nextPageAction()
330   {
331     UniProtFTSRestClient c = UniProtFTSRestClient.getInstance();
332     String nextCursor = c.getNextCursor();
333     if (nextCursor != null)
334     {
335       offSet += pageLimit;
336       c.setNextCursorPage();
337       searchAction(nextCursor, false);
338     }
339     else
340     {
341       refreshPaginatorState();
342     }
343   }
344
345   public String getDbName()
346   {
347     return "UniProt";
348   }
349 }