JAL-2446 merged to spike branch
[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<String, UrlLink>();
111
112     StringTokenizer st = new StringTokenizer(urlStrings, SEP);
113     while (st.hasMoreElements())
114     {
115       String name = st.nextToken();
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         urls.put(name, new UrlLink(name, url, name));
133       }
134     }
135     upgradeOldLinks(urls);
136     return urls;
137   }
138
139   private HashMap<String, UrlLink> parseUrlList(Map<String, String> urlList)
140   {
141     HashMap<String, UrlLink> urls = new HashMap<String, UrlLink>();
142     if (urlList == null)
143     {
144       return urls;
145     }
146
147     Iterator<Map.Entry<String, String>> it = urlList.entrySet().iterator();
148     while (it.hasNext())
149     {
150       Map.Entry<String, String> pair = it.next();
151       urls.put(pair.getKey(),
152  new UrlLink(pair.getKey(), pair.getValue(),
153               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     // upgrade old SRS link
165     if (urls.containsKey(SRS_LABEL))
166     {
167       urls.remove(SRS_LABEL);
168       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
169       link.setLabel(UrlConstants.DEFAULT_LABEL);
170       urls.put(UrlConstants.DEFAULT_LABEL, link);
171     }
172   }
173
174   @Override
175   public List<String> getLinksForMenu()
176   {
177     List<String> links = new ArrayList<String>();
178     Iterator<Map.Entry<String, UrlLink>> it = selectedUrls.entrySet()
179             .iterator();
180     while (it.hasNext())
181     {
182       Map.Entry<String, UrlLink> pair = it.next();
183       links.add(pair.getValue().toString());
184     }
185     return links;
186   }
187
188   @Override
189   public List<UrlLinkDisplay> getLinksForTable()
190   {
191     ArrayList<UrlLinkDisplay> displayLinks = new ArrayList<UrlLinkDisplay>();
192     displayLinks = getLinksForTable(selectedUrls, true);
193     displayLinks.addAll(getLinksForTable(nonselectedUrls, false));
194     return displayLinks;
195   }
196
197   private ArrayList<UrlLinkDisplay> getLinksForTable(
198           HashMap<String, UrlLink> urlList, boolean selected)
199   {
200     return super.getLinksForTable(urlList, null, selected);
201   }
202
203   @Override
204   public boolean setPrimaryUrl(String id)
205   {
206     if (selectedUrls.containsKey(id))
207     {
208       primaryUrl = id;
209     }
210     else if (nonselectedUrls.containsKey(id))
211     {
212       primaryUrl = id;
213     }
214     else
215     {
216       primaryUrl = null;
217     }
218
219     return (primaryUrl != null);
220   }
221
222   @Override
223   public String writeUrlsAsString(boolean selected)
224   {
225     StringBuffer links = new StringBuffer();
226     HashMap<String, UrlLink> urls;
227     if (selected)
228     {
229       urls = selectedUrls;
230     }
231     else
232     {
233       urls = nonselectedUrls;
234     }
235     if (urls.size() > 0)
236     {
237       for (Entry<String, UrlLink> entry : urls.entrySet())
238       {
239         links.append(entry.getValue().toString());
240         links.append(SEP);
241       }
242
243       // remove last SEP
244       links.setLength(links.length() - 1);
245     }
246     else
247     {
248       urls.clear();
249     }
250     return links.toString();
251   }
252
253   @Override
254   public String getPrimaryUrl(String seqid)
255   {
256     String result = super.getPrimaryUrl(seqid, selectedUrls);
257     if (result == null)
258     {
259       result = super.getPrimaryUrl(seqid, nonselectedUrls);
260     }
261     return result;
262   }
263
264   @Override
265   public String getPrimaryUrlId()
266   {
267     return primaryUrl;
268   }
269
270   @Override
271   public String getPrimaryTarget(String seqid)
272   {
273     return selectedUrls.get(primaryUrl).getTarget();
274   }
275
276   @Override
277   public void setUrlData(List<UrlLinkDisplay> links)
278   {
279     HashMap<String, UrlLink> unselurls = new HashMap<String, UrlLink>();
280     HashMap<String, UrlLink> selurls = new HashMap<String, UrlLink>();
281
282     Iterator<UrlLinkDisplay> it = links.iterator();
283     while (it.hasNext())
284     {
285       UrlLinkDisplay link = it.next();
286
287       // MIRIAM ids will be handled by a different UrlProvider class
288       if (!isMiriamId(link.getId()))
289       {
290         // don't allow duplicate key names as entries will be overwritten
291         if (unselurls.containsKey(link.getId())
292                 || selurls.containsKey(link.getId()))
293         {
294           throw new IllegalArgumentException(MessageManager.formatMessage(
295                   "exception.url_cannot_have_duplicate_id", link.getId()));
296         }
297         if (link.getIsSelected())
298         {
299           selurls.put(link.getId(),
300                   new UrlLink(link.getDescription(), link.getUrl(), link.getDescription()));
301         }
302         else
303         {
304           unselurls
305                   .put(link.getId(),
306                           new UrlLink(link.getDescription(), link.getUrl(), link
307                                   .getDescription()));
308         }
309         // sort out primary and selected ids
310         if (link.getIsPrimary())
311         {
312           setPrimaryUrl(link.getId());
313         }
314       }
315
316     }
317     nonselectedUrls = unselurls;
318     selectedUrls = selurls;
319   }
320
321   @Override
322   public String choosePrimaryUrl()
323   {
324     // unilaterally set the primary id to the EMBL_EBI link
325     if ((!nonselectedUrls.containsKey(UrlConstants.DEFAULT_LABEL))
326             && (!selectedUrls.containsKey(UrlConstants.DEFAULT_LABEL)))
327     {
328       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
329       link.setLabel(UrlConstants.DEFAULT_LABEL);
330       selectedUrls.put(UrlConstants.DEFAULT_LABEL, link);
331     }
332     primaryUrl = UrlConstants.DEFAULT_LABEL;
333     return UrlConstants.DEFAULT_LABEL;
334   }
335
336   @Override
337   public boolean contains(String id)
338   {
339     return (selectedUrls.containsKey(id) || nonselectedUrls.containsKey(id));
340   }
341
342 }