JAL-4020 Added search for PyMOLWinWithConsole.bat (and PyMOLWin.exe) in likely places...
[jalview.git] / src / jalview / urls / CustomUrlProvider.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.urls;
23
24 import static jalview.util.UrlConstants.DB_ACCESSION;
25 import static jalview.util.UrlConstants.DELIM;
26 import static jalview.util.UrlConstants.SEP;
27 import static jalview.util.UrlConstants.SEQUENCE_ID;
28
29 import jalview.util.MessageManager;
30 import jalview.util.UrlConstants;
31 import jalview.util.UrlLink;
32
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.StringTokenizer;
40
41 /**
42  * 
43  * Implements the UrlProviderI interface for a UrlProvider object which serves
44  * custom URLs defined by the user
45  * 
46  * @author $author$
47  * @version $Revision$
48  */
49 public class CustomUrlProvider extends UrlProviderImpl
50 {
51   // Default sequence URL link label for SRS
52   private static final String SRS_LABEL = "SRS";
53
54   // map of string ids to urlLinks (selected)
55   private HashMap<String, UrlLink> selectedUrls;
56
57   // map of string ids to urlLinks (not selected)
58   private HashMap<String, UrlLink> nonselectedUrls;
59
60   /**
61    * Construct UrlProvider for custom (user-entered) URLs
62    * 
63    * @param inMenuUrlList
64    *          list of URLs set to be displayed in menu, in form stored in Cache.
65    *          i.e. SEP delimited string
66    * @param storedUrlList
67    *          list of custom URLs entered by user but not currently displayed in
68    *          menu, in form stored in Cache
69    */
70   public CustomUrlProvider(String inMenuUrlList, String storedUrlList)
71   {
72     try
73     {
74       selectedUrls = parseUrlStrings(inMenuUrlList);
75       nonselectedUrls = parseUrlStrings(storedUrlList);
76     } catch (Exception ex)
77     {
78       System.out
79               .println(ex.getMessage() + "\nError parsing sequence links");
80     }
81   }
82
83   /**
84    * Construct UrlProvider for custom (user-entered) URLs
85    * 
86    * @param urlList
87    *          list of URLs to be displayed in menu, as (label,url) pairs
88    * @param storedUrlList
89    *          list of custom URLs entered by user but not currently displayed in
90    *          menu, as (label,url) pairs
91    */
92   public CustomUrlProvider(Map<String, String> inMenuUrlList,
93           Map<String, String> storedUrlList)
94   {
95     try
96     {
97       selectedUrls = parseUrlList(inMenuUrlList);
98       nonselectedUrls = parseUrlList(storedUrlList);
99     } catch (Exception ex)
100     {
101       System.out
102               .println(ex.getMessage() + "\nError parsing sequence links");
103     }
104   }
105
106   private HashMap<String, UrlLink> parseUrlStrings(String urlStrings)
107   {
108     // cachedUrlList is in form <label>|<url>|<label>|<url>...
109     // parse cachedUrlList into labels (used as id) and url links
110     HashMap<String, UrlLink> urls = new HashMap<>();
111
112     StringTokenizer st = new StringTokenizer(urlStrings, SEP);
113     while (st.hasMoreElements())
114     {
115       String name = st.nextToken().trim();
116
117       if (!isMiriamId(name))
118       {
119         // this one of our custom urls
120         String url = st.nextToken();
121         // check for '|' within a regex
122         int rxstart = url.indexOf(DELIM + DB_ACCESSION + DELIM);
123         if (rxstart == -1)
124         {
125           rxstart = url.indexOf(DELIM + SEQUENCE_ID + DELIM);
126         }
127         while (rxstart == -1 && url.indexOf("/=" + DELIM) == -1
128                 && st.hasMoreTokens())
129         {
130           url = url + SEP + st.nextToken();
131         }
132         url = url.trim();
133         urls.put(name, new UrlLink(name, url, name));
134       }
135     }
136     upgradeOldLinks(urls);
137     return urls;
138   }
139
140   private HashMap<String, UrlLink> parseUrlList(Map<String, String> urlList)
141   {
142     HashMap<String, UrlLink> urls = new HashMap<>();
143     if (urlList == null)
144     {
145       return urls;
146     }
147
148     Iterator<Map.Entry<String, String>> it = urlList.entrySet().iterator();
149     while (it.hasNext())
150     {
151       Map.Entry<String, String> pair = it.next();
152       urls.put(pair.getKey(),
153               new UrlLink(pair.getKey(), pair.getValue(), pair.getKey()));
154     }
155     upgradeOldLinks(urls);
156     return urls;
157   }
158
159   /*
160    * Upgrade any legacy links which may have been left lying around
161    */
162   private void upgradeOldLinks(HashMap<String, UrlLink> urls)
163   {
164     boolean upgrade = false;
165     // upgrade old SRS link
166     if (urls.containsKey(SRS_LABEL))
167     {
168       urls.remove(SRS_LABEL);
169       upgrade = true;
170     }
171     // upgrade old EBI link - easier just to remove and re-add than faffing
172     // around checking exact url
173     if (urls.containsKey(UrlConstants.DEFAULT_LABEL))
174     {
175       // note because this is called separately for selected and nonselected
176       // urls, the default url will not always be present
177       urls.remove(UrlConstants.DEFAULT_LABEL);
178       upgrade = true;
179     }
180     if (upgrade)
181     {
182       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
183       link.setLabel(UrlConstants.DEFAULT_LABEL);
184       urls.put(UrlConstants.DEFAULT_LABEL, link);
185     }
186   }
187
188   @Override
189   public List<String> getLinksForMenu()
190   {
191     List<String> links = new ArrayList<>();
192     Iterator<Map.Entry<String, UrlLink>> it = selectedUrls.entrySet()
193             .iterator();
194     while (it.hasNext())
195     {
196       Map.Entry<String, UrlLink> pair = it.next();
197       links.add(pair.getValue().toString());
198     }
199     return links;
200   }
201
202   @Override
203   public List<UrlLinkDisplay> getLinksForTable()
204   {
205     ArrayList<UrlLinkDisplay> displayLinks = new ArrayList<>();
206     displayLinks = getLinksForTable(selectedUrls, true);
207     displayLinks.addAll(getLinksForTable(nonselectedUrls, false));
208     return displayLinks;
209   }
210
211   private ArrayList<UrlLinkDisplay> getLinksForTable(
212           HashMap<String, UrlLink> urlList, boolean selected)
213   {
214     return super.getLinksForTable(urlList, null, selected);
215   }
216
217   @Override
218   public boolean setPrimaryUrl(String id)
219   {
220     if (selectedUrls.containsKey(id))
221     {
222       primaryUrl = id;
223     }
224     else if (nonselectedUrls.containsKey(id))
225     {
226       primaryUrl = id;
227     }
228     else
229     {
230       primaryUrl = null;
231     }
232
233     return (primaryUrl != null);
234   }
235
236   @Override
237   public String writeUrlsAsString(boolean selected)
238   {
239     StringBuffer links = new StringBuffer();
240     HashMap<String, UrlLink> urls;
241     if (selected)
242     {
243       urls = selectedUrls;
244     }
245     else
246     {
247       urls = nonselectedUrls;
248     }
249     if (urls.size() > 0)
250     {
251       for (Entry<String, UrlLink> entry : urls.entrySet())
252       {
253         links.append(entry.getValue().toString());
254         links.append(SEP);
255       }
256
257       // remove last SEP
258       links.setLength(links.length() - 1);
259     }
260     else
261     {
262       urls.clear();
263     }
264     return links.toString();
265   }
266
267   @Override
268   public String getPrimaryUrl(String seqid)
269   {
270     String result = super.getPrimaryUrl(seqid, selectedUrls);
271     if (result == null)
272     {
273       result = super.getPrimaryUrl(seqid, nonselectedUrls);
274     }
275     return result;
276   }
277
278   @Override
279   public String getPrimaryUrlId()
280   {
281     return primaryUrl;
282   }
283
284   @Override
285   public String getPrimaryTarget(String seqid)
286   {
287     return selectedUrls.get(primaryUrl).getTarget();
288   }
289
290   @Override
291   public void setUrlData(List<UrlLinkDisplay> links)
292   {
293     HashMap<String, UrlLink> unselurls = new HashMap<>();
294     HashMap<String, UrlLink> selurls = new HashMap<>();
295
296     Iterator<UrlLinkDisplay> it = links.iterator();
297     while (it.hasNext())
298     {
299       UrlLinkDisplay link = it.next();
300
301       // MIRIAM ids will be handled by a different UrlProvider class
302       if (!isMiriamId(link.getId()))
303       {
304         // don't allow duplicate key names as entries will be overwritten
305         if (unselurls.containsKey(link.getId())
306                 || selurls.containsKey(link.getId()))
307         {
308           throw new IllegalArgumentException(MessageManager.formatMessage(
309                   "exception.url_cannot_have_duplicate_id", link.getId()));
310         }
311         if (link.getIsSelected())
312         {
313           selurls.put(link.getId(), new UrlLink(link.getDescription(),
314                   link.getUrl(), link.getDescription()));
315         }
316         else
317         {
318           unselurls.put(link.getId(), new UrlLink(link.getDescription(),
319                   link.getUrl(), link.getDescription()));
320         }
321         // sort out primary and selected ids
322         if (link.getIsPrimary())
323         {
324           setPrimaryUrl(link.getId());
325         }
326       }
327
328     }
329     nonselectedUrls = unselurls;
330     selectedUrls = selurls;
331   }
332
333   @Override
334   public String choosePrimaryUrl()
335   {
336     // unilaterally set the primary id to the EMBL_EBI link
337     if ((!nonselectedUrls.containsKey(UrlConstants.DEFAULT_LABEL))
338             && (!selectedUrls.containsKey(UrlConstants.DEFAULT_LABEL)))
339     {
340       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
341       link.setLabel(UrlConstants.DEFAULT_LABEL);
342       selectedUrls.put(UrlConstants.DEFAULT_LABEL, link);
343     }
344     primaryUrl = UrlConstants.DEFAULT_LABEL;
345     return UrlConstants.DEFAULT_LABEL;
346   }
347
348   @Override
349   public boolean contains(String id)
350   {
351     return (selectedUrls.containsKey(id)
352             || nonselectedUrls.containsKey(id));
353   }
354
355 }