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